• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/memory/scoped_ptr.h"
6 #include "base/memory/weak_ptr.h"
7 #include "content/browser/gamepad/gamepad_data_fetcher.h"
8 #include "content/browser/gamepad/gamepad_provider.h"
9 #include "content/browser/gamepad/gamepad_test_helpers.h"
10 #include "content/common/gamepad_hardware_buffer.h"
11 #include "content/common/gamepad_messages.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace content {
15 
16 namespace {
17 
18 using blink::WebGamepads;
19 
20 // Helper class to generate and record user gesture callbacks.
21 class UserGestureListener {
22  public:
UserGestureListener()23   UserGestureListener()
24       : weak_factory_(this),
25         has_user_gesture_(false) {
26   }
27 
GetClosure()28   base::Closure GetClosure() {
29     return base::Bind(&UserGestureListener::GotUserGesture,
30                       weak_factory_.GetWeakPtr());
31   }
32 
has_user_gesture() const33   bool has_user_gesture() const { return has_user_gesture_; }
34 
35  private:
GotUserGesture()36   void GotUserGesture() {
37     has_user_gesture_ = true;
38   }
39 
40   base::WeakPtrFactory<UserGestureListener> weak_factory_;
41   bool has_user_gesture_;
42 };
43 
44 // Main test fixture
45 class GamepadProviderTest : public testing::Test, public GamepadTestHelper {
46  public:
CreateProvider(const WebGamepads & test_data)47   GamepadProvider* CreateProvider(const WebGamepads& test_data) {
48     mock_data_fetcher_ = new MockGamepadDataFetcher(test_data);
49     provider_.reset(new GamepadProvider(
50         scoped_ptr<GamepadDataFetcher>(mock_data_fetcher_)));
51     return provider_.get();
52   }
53 
54  protected:
GamepadProviderTest()55   GamepadProviderTest() {
56   }
57 
58   scoped_ptr<GamepadProvider> provider_;
59 
60   // Pointer owned by the provider.
61   MockGamepadDataFetcher* mock_data_fetcher_;
62 
63   DISALLOW_COPY_AND_ASSIGN(GamepadProviderTest);
64 };
65 
66 // Crashes. http://crbug.com/106163
TEST_F(GamepadProviderTest,PollingAccess)67 TEST_F(GamepadProviderTest, PollingAccess) {
68   WebGamepads test_data;
69   test_data.length = 1;
70   test_data.items[0].connected = true;
71   test_data.items[0].timestamp = 0;
72   test_data.items[0].buttonsLength = 1;
73   test_data.items[0].axesLength = 2;
74   test_data.items[0].buttons[0].value = 1.f;
75   test_data.items[0].buttons[0].pressed = true;
76   test_data.items[0].axes[0] = -1.f;
77   test_data.items[0].axes[1] = .5f;
78 
79   GamepadProvider* provider = CreateProvider(test_data);
80   provider->Resume();
81 
82   message_loop().RunUntilIdle();
83 
84   mock_data_fetcher_->WaitForDataRead();
85 
86   // Renderer-side, pull data out of poll buffer.
87   base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess(
88       base::GetCurrentProcessHandle());
89   scoped_ptr<base::SharedMemory> shared_memory(
90       new base::SharedMemory(handle, true));
91   EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer)));
92   void* mem = shared_memory->memory();
93 
94   GamepadHardwareBuffer* hwbuf = static_cast<GamepadHardwareBuffer*>(mem);
95   // See gamepad_hardware_buffer.h for details on the read discipline.
96   WebGamepads output;
97 
98   base::subtle::Atomic32 version;
99   do {
100     version = hwbuf->sequence.ReadBegin();
101     memcpy(&output, &hwbuf->buffer, sizeof(output));
102   } while (hwbuf->sequence.ReadRetry(version));
103 
104   EXPECT_EQ(1u, output.length);
105   EXPECT_EQ(1u, output.items[0].buttonsLength);
106   EXPECT_EQ(1.f, output.items[0].buttons[0].value);
107   EXPECT_EQ(true, output.items[0].buttons[0].pressed);
108   EXPECT_EQ(2u, output.items[0].axesLength);
109   EXPECT_EQ(-1.f, output.items[0].axes[0]);
110   EXPECT_EQ(0.5f, output.items[0].axes[1]);
111 }
112 
113 // Tests that waiting for a user gesture works properly.
TEST_F(GamepadProviderTest,UserGesture)114 TEST_F(GamepadProviderTest, UserGesture) {
115   WebGamepads no_button_data;
116   no_button_data.length = 1;
117   no_button_data.items[0].connected = true;
118   no_button_data.items[0].timestamp = 0;
119   no_button_data.items[0].buttonsLength = 1;
120   no_button_data.items[0].axesLength = 2;
121   no_button_data.items[0].buttons[0].value = 0.f;
122   no_button_data.items[0].buttons[0].pressed = false;
123   no_button_data.items[0].axes[0] = -1.f;
124   no_button_data.items[0].axes[1] = .5f;
125 
126   WebGamepads button_down_data = no_button_data;
127   button_down_data.items[0].buttons[0].value = 1.f;
128   button_down_data.items[0].buttons[0].pressed = true;
129 
130   UserGestureListener listener;
131   GamepadProvider* provider = CreateProvider(no_button_data);
132   provider->Resume();
133 
134   provider->RegisterForUserGesture(listener.GetClosure());
135   mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
136 
137   // It should not have issued our callback.
138   message_loop().RunUntilIdle();
139   EXPECT_FALSE(listener.has_user_gesture());
140 
141   // Set a button down and wait for it to be read twice.
142   mock_data_fetcher_->SetTestData(button_down_data);
143   mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
144 
145   // It should have issued our callback.
146   message_loop().RunUntilIdle();
147   EXPECT_TRUE(listener.has_user_gesture());
148 }
149 
150 }  // namespace
151 
152 }  // namespace content
153