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.
7 #include "base/memory/scoped_ptr.h"
8 #include "base/memory/weak_ptr.h"
9 #include "content/browser/gamepad/gamepad_test_helpers.h"
10 #include "content/browser/renderer_host/pepper/browser_ppapi_host_test.h"
11 #include "content/browser/renderer_host/pepper/pepper_gamepad_host.h"
12 #include "content/common/gamepad_hardware_buffer.h"
13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/host/host_message_context.h"
15 #include "ppapi/proxy/gamepad_resource.h"
16 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ppapi/proxy/resource_message_params.h"
18 #include "ppapi/shared_impl/ppb_gamepad_shared.h"
19 #include "testing/gtest/include/gtest/gtest.h"
25 class PepperGamepadHostTest
: public testing::Test
,
26 public BrowserPpapiHostTest
{
28 PepperGamepadHostTest() {}
29 virtual ~PepperGamepadHostTest() {}
31 void ConstructService(const blink::WebGamepads
& test_data
) {
32 service_
.reset(new GamepadServiceTestConstructor(test_data
));
35 GamepadService
* gamepad_service() { return service_
->gamepad_service(); }
38 scoped_ptr
<GamepadServiceTestConstructor
> service_
;
40 DISALLOW_COPY_AND_ASSIGN(PepperGamepadHostTest
);
43 inline ptrdiff_t AddressDiff(const void* a
, const void* b
) {
44 return static_cast<const char*>(a
) - static_cast<const char*>(b
);
49 // Validate the memory layout of the Pepper proxy struct matches the content
50 // one. The proxy can't depend on content so has a duplicate definition. This
51 // code can see both definitions so we do the validation here.
52 TEST_F(PepperGamepadHostTest
, ValidateHardwareBuffersMatch
) {
54 COMPILE_ASSERT(sizeof(ppapi::ContentGamepadHardwareBuffer
) ==
55 sizeof(GamepadHardwareBuffer
),
56 gamepad_hardware_buffers_must_match
);
57 ppapi::ContentGamepadHardwareBuffer ppapi_buf
;
58 GamepadHardwareBuffer content_buf
;
59 EXPECT_EQ(AddressDiff(&content_buf
.sequence
, &content_buf
),
60 AddressDiff(&ppapi_buf
.sequence
, &ppapi_buf
));
61 EXPECT_EQ(AddressDiff(&content_buf
.buffer
, &content_buf
),
62 AddressDiff(&ppapi_buf
.buffer
, &ppapi_buf
));
65 TEST_F(PepperGamepadHostTest
, ValidateGamepadsMatch
) {
67 COMPILE_ASSERT(sizeof(ppapi::WebKitGamepads
) == sizeof(blink::WebGamepads
),
68 gamepads_data_must_match
);
69 ppapi::WebKitGamepads ppapi_gamepads
;
70 blink::WebGamepads web_gamepads
;
71 EXPECT_EQ(AddressDiff(&web_gamepads
.length
, &web_gamepads
),
72 AddressDiff(&ppapi_gamepads
.length
, &ppapi_gamepads
));
74 // See comment below on storage & the EXPECT macro.
75 size_t webkit_items_length_cap
= blink::WebGamepads::itemsLengthCap
;
76 size_t ppapi_items_length_cap
= ppapi::WebKitGamepads::kItemsLengthCap
;
77 EXPECT_EQ(webkit_items_length_cap
, ppapi_items_length_cap
);
79 for (size_t i
= 0; i
< web_gamepads
.itemsLengthCap
; i
++) {
80 EXPECT_EQ(AddressDiff(&web_gamepads
.items
[0], &web_gamepads
),
81 AddressDiff(&ppapi_gamepads
.items
[0], &ppapi_gamepads
));
85 TEST_F(PepperGamepadHostTest
, ValidateGamepadMatch
) {
87 COMPILE_ASSERT(sizeof(ppapi::WebKitGamepad
) == sizeof(blink::WebGamepad
),
88 gamepad_data_must_match
);
89 ppapi::WebKitGamepad ppapi_gamepad
;
90 blink::WebGamepad web_gamepad
;
92 // Using EXPECT seems to force storage for the parameter, which the constants
93 // in the WebKit/PPAPI headers don't have. So we have to use temporaries
94 // before comparing them.
95 size_t webkit_id_length_cap
= blink::WebGamepad::idLengthCap
;
96 size_t ppapi_id_length_cap
= ppapi::WebKitGamepad::kIdLengthCap
;
97 EXPECT_EQ(webkit_id_length_cap
, ppapi_id_length_cap
);
99 size_t webkit_axes_length_cap
= blink::WebGamepad::axesLengthCap
;
100 size_t ppapi_axes_length_cap
= ppapi::WebKitGamepad::kAxesLengthCap
;
101 EXPECT_EQ(webkit_axes_length_cap
, ppapi_axes_length_cap
);
103 size_t webkit_buttons_length_cap
= blink::WebGamepad::buttonsLengthCap
;
104 size_t ppapi_buttons_length_cap
= ppapi::WebKitGamepad::kButtonsLengthCap
;
105 EXPECT_EQ(webkit_buttons_length_cap
, ppapi_buttons_length_cap
);
107 EXPECT_EQ(AddressDiff(&web_gamepad
.connected
, &web_gamepad
),
108 AddressDiff(&ppapi_gamepad
.connected
, &ppapi_gamepad
));
109 EXPECT_EQ(AddressDiff(&web_gamepad
.id
, &web_gamepad
),
110 AddressDiff(&ppapi_gamepad
.id
, &ppapi_gamepad
));
111 EXPECT_EQ(AddressDiff(&web_gamepad
.timestamp
, &web_gamepad
),
112 AddressDiff(&ppapi_gamepad
.timestamp
, &ppapi_gamepad
));
113 EXPECT_EQ(AddressDiff(&web_gamepad
.axesLength
, &web_gamepad
),
114 AddressDiff(&ppapi_gamepad
.axes_length
, &ppapi_gamepad
));
115 EXPECT_EQ(AddressDiff(&web_gamepad
.axes
, &web_gamepad
),
116 AddressDiff(&ppapi_gamepad
.axes
, &ppapi_gamepad
));
117 EXPECT_EQ(AddressDiff(&web_gamepad
.buttonsLength
, &web_gamepad
),
118 AddressDiff(&ppapi_gamepad
.buttons_length
, &ppapi_gamepad
));
119 EXPECT_EQ(AddressDiff(&web_gamepad
.buttons
, &web_gamepad
),
120 AddressDiff(&ppapi_gamepad
.buttons
, &ppapi_gamepad
));
123 TEST_F(PepperGamepadHostTest
, WaitForReply
) {
124 blink::WebGamepads default_data
;
125 memset(&default_data
, 0, sizeof(blink::WebGamepads
));
126 default_data
.length
= 1;
127 default_data
.items
[0].connected
= true;
128 default_data
.items
[0].buttonsLength
= 1;
129 ConstructService(default_data
);
131 PP_Instance pp_instance
= 12345;
132 PP_Resource pp_resource
= 67890;
133 PepperGamepadHost
gamepad_host(
134 gamepad_service(), GetBrowserPpapiHost(), pp_instance
, pp_resource
);
136 // Synthesize a request for gamepad data.
137 ppapi::host::HostMessageContext
context(
138 ppapi::proxy::ResourceMessageCallParams(pp_resource
, 1));
139 EXPECT_EQ(PP_OK_COMPLETIONPENDING
,
140 gamepad_host
.OnResourceMessageReceived(
141 PpapiHostMsg_Gamepad_RequestMemory(), &context
));
143 // Wait for the gamepad background thread to read twice to make sure we
144 // don't get a message yet (see below for why).
145 MockGamepadDataFetcher
* fetcher
= service_
->data_fetcher();
146 fetcher
->WaitForDataRead();
147 fetcher
->WaitForDataRead();
149 // It should not have sent the callback message.
150 service_
->message_loop().RunUntilIdle();
151 EXPECT_EQ(0u, sink().message_count());
153 // Set a button down and wait for it to be read twice.
155 // We wait for two reads before calling RunAllPending because the provider
156 // will read the data on the background thread (setting the event) and *then*
157 // will issue the callback on our thread. Waiting for it to read twice
158 // ensures that it was able to issue callbacks for the first read (if it
159 // issued one) before we try to check for it.
160 blink::WebGamepads button_down_data
= default_data
;
161 button_down_data
.items
[0].buttons
[0].value
= 1.f
;
162 button_down_data
.items
[0].buttons
[0].pressed
= true;
163 fetcher
->SetTestData(button_down_data
);
164 fetcher
->WaitForDataRead();
165 fetcher
->WaitForDataRead();
167 // It should have sent a callback.
168 service_
->message_loop().RunUntilIdle();
169 ppapi::proxy::ResourceMessageReplyParams reply_params
;
170 IPC::Message reply_msg
;
171 ASSERT_TRUE(sink().GetFirstResourceReplyMatching(
172 PpapiPluginMsg_Gamepad_SendMemory::ID
, &reply_params
, &reply_msg
));
174 // Extract the shared memory handle.
175 base::SharedMemoryHandle reply_handle
;
176 EXPECT_TRUE(reply_params
.TakeSharedMemoryHandleAtIndex(0, &reply_handle
));
178 // Validate the shared memory.
179 base::SharedMemory
shared_memory(reply_handle
, true);
180 EXPECT_TRUE(shared_memory
.Map(sizeof(ppapi::ContentGamepadHardwareBuffer
)));
181 const ppapi::ContentGamepadHardwareBuffer
* buffer
=
182 static_cast<const ppapi::ContentGamepadHardwareBuffer
*>(
183 shared_memory
.memory());
184 EXPECT_EQ(button_down_data
.length
, buffer
->buffer
.length
);
185 EXPECT_EQ(button_down_data
.items
[0].buttonsLength
,
186 buffer
->buffer
.items
[0].buttons_length
);
187 for (size_t i
= 0; i
< ppapi::WebKitGamepad::kButtonsLengthCap
; i
++) {
188 EXPECT_EQ(button_down_data
.items
[0].buttons
[i
].value
,
189 buffer
->buffer
.items
[0].buttons
[i
].value
);
190 EXPECT_EQ(button_down_data
.items
[0].buttons
[i
].pressed
,
191 buffer
->buffer
.items
[0].buttons
[i
].pressed
);
194 // Duplicate requests should be denied.
195 EXPECT_EQ(PP_ERROR_FAILED
,
196 gamepad_host
.OnResourceMessageReceived(
197 PpapiHostMsg_Gamepad_RequestMemory(), &context
));
200 } // namespace content