summaryrefslogtreecommitdiffstats
path: root/content/browser/gamepad/gamepad_service.h
blob: 22bea8c02a850cd230f5ca2a07b68925dbf899c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) 2012 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.

#ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_SERVICE_H_
#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_SERVICE_H_

#include <set>

#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/memory/singleton.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"

namespace blink {
class WebGamepad;
}

namespace content {

class GamepadConsumer;
class GamepadDataFetcher;
class GamepadProvider;
class GamepadServiceTestConstructor;
class RenderProcessHost;

// Owns the GamepadProvider (the background polling thread) and keeps track of
// the number of consumers currently using the data (and pausing the provider
// when not in use).
class CONTENT_EXPORT GamepadService {
 public:
  // Returns the GamepadService singleton.
  static GamepadService* GetInstance();

  // Increments the number of users of the provider. The Provider is running
  // when there's > 0 users, and is paused when the count drops to 0.
  // consumer is registered to listen for gamepad connections. If this is the
  // first time it is added to the set of consumers it will be treated
  // specially: it will not be informed about connections before a new user
  // gesture is observed at which point it will be notified for every connected
  // gamepads.
  //
  // Must be called on the I/O thread.
  void ConsumerBecameActive(GamepadConsumer* consumer);

  // Decrements the number of users of the provider. consumer will not be
  // informed about connections until it's added back via ConsumerBecameActive.
  // Must be matched with a ConsumerBecameActive call.
  //
  // Must be called on the I/O thread.
  void ConsumerBecameInactive(GamepadConsumer* consumer);

  // Decrements the number of users of the provider and removes consumer from
  // the set of consumers. Should be matched with a a ConsumerBecameActive
  // call.
  //
  // Must be called on the I/O thread.
  void RemoveConsumer(GamepadConsumer* consumer);

  // Registers the given closure for calling when the user has interacted with
  // the device. This callback will only be issued once. Should only be called
  // while a consumer is active.
  void RegisterForUserGesture(const base::Closure& closure);

  // Returns the shared memory handle of the gamepad data duplicated into the
  // given process.
  base::SharedMemoryHandle GetSharedMemoryHandleForProcess(
      base::ProcessHandle handle);

  // Stop/join with the background thread in GamepadProvider |provider_|.
  void Terminate();

  // Called on IO thread when a gamepad is connected.
  void OnGamepadConnected(int index, const blink::WebGamepad& pad);

  // Called on IO thread when a gamepad is disconnected.
  void OnGamepadDisconnected(int index, const blink::WebGamepad& pad);

 private:
  friend struct base::DefaultSingletonTraits<GamepadService>;
  friend class GamepadServiceTestConstructor;
  friend class GamepadServiceTest;

  GamepadService();

  // Constructor for testing. This specifies the data fetcher to use for a
  // provider, bypassing the default platform one.
  GamepadService(scoped_ptr<GamepadDataFetcher> fetcher);

  virtual ~GamepadService();

  static void SetInstance(GamepadService*);

  void OnUserGesture();

  struct ConsumerInfo {
    ConsumerInfo(GamepadConsumer* consumer)
        : consumer(consumer),
          did_observe_user_gesture(false) {
    }

    bool operator<(const ConsumerInfo& other) const {
      return consumer < other.consumer;
    }

    GamepadConsumer* consumer;
    mutable bool is_active;
    mutable bool did_observe_user_gesture;
  };

  scoped_ptr<GamepadProvider> provider_;

  base::ThreadChecker thread_checker_;

  typedef std::set<ConsumerInfo> ConsumerSet;
  ConsumerSet consumers_;

  int num_active_consumers_;

  bool gesture_callback_pending_;

  DISALLOW_COPY_AND_ASSIGN(GamepadService);
};

}  // namespace content

#endif  // CONTENT_BROWSER_GAMEPAD_GAMEPAD_SERVICE_H_