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 <string.h> 6 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" 20 21namespace content { 22 23namespace { 24 25class PepperGamepadHostTest : public testing::Test, 26 public BrowserPpapiHostTest { 27 public: 28 PepperGamepadHostTest() {} 29 virtual ~PepperGamepadHostTest() {} 30 31 void ConstructService(const blink::WebGamepads& test_data) { 32 service_.reset(new GamepadServiceTestConstructor(test_data)); 33 } 34 35 GamepadService* gamepad_service() { return service_->gamepad_service(); } 36 37 protected: 38 scoped_ptr<GamepadServiceTestConstructor> service_; 39 40 DISALLOW_COPY_AND_ASSIGN(PepperGamepadHostTest); 41}; 42 43inline ptrdiff_t AddressDiff(const void* a, const void* b) { 44 return static_cast<const char*>(a) - static_cast<const char*>(b); 45} 46 47} // namespace 48 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. 52TEST_F(PepperGamepadHostTest, ValidateHardwareBuffersMatch) { 53 // Hardware buffer. 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)); 63} 64 65TEST_F(PepperGamepadHostTest, ValidateGamepadsMatch) { 66 // Gamepads. 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)); 73 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); 78 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)); 82 } 83} 84 85TEST_F(PepperGamepadHostTest, ValidateGamepadMatch) { 86 // Gamepad. 87 COMPILE_ASSERT(sizeof(ppapi::WebKitGamepad) == sizeof(blink::WebGamepad), 88 gamepad_data_must_match); 89 ppapi::WebKitGamepad ppapi_gamepad; 90 blink::WebGamepad web_gamepad; 91 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); 98 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); 102 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); 106 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)); 121} 122 123TEST_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); 130 131 PP_Instance pp_instance = 12345; 132 PP_Resource pp_resource = 67890; 133 PepperGamepadHost gamepad_host( 134 gamepad_service(), GetBrowserPpapiHost(), pp_instance, pp_resource); 135 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)); 142 143 MockGamepadDataFetcher* fetcher = service_->data_fetcher(); 144 fetcher->WaitForDataReadAndCallbacksIssued(); 145 146 // It should not have sent the callback message. 147 service_->message_loop().RunUntilIdle(); 148 EXPECT_EQ(0u, sink().message_count()); 149 150 // Set a button down and wait for it to be read twice. 151 blink::WebGamepads button_down_data = default_data; 152 button_down_data.items[0].buttons[0].value = 1.f; 153 button_down_data.items[0].buttons[0].pressed = true; 154 fetcher->SetTestData(button_down_data); 155 fetcher->WaitForDataReadAndCallbacksIssued(); 156 157 // It should have sent a callback. 158 service_->message_loop().RunUntilIdle(); 159 ppapi::proxy::ResourceMessageReplyParams reply_params; 160 IPC::Message reply_msg; 161 ASSERT_TRUE(sink().GetFirstResourceReplyMatching( 162 PpapiPluginMsg_Gamepad_SendMemory::ID, &reply_params, &reply_msg)); 163 164 // Extract the shared memory handle. 165 base::SharedMemoryHandle reply_handle; 166 EXPECT_TRUE(reply_params.TakeSharedMemoryHandleAtIndex(0, &reply_handle)); 167 168 // Validate the shared memory. 169 base::SharedMemory shared_memory(reply_handle, true); 170 EXPECT_TRUE(shared_memory.Map(sizeof(ppapi::ContentGamepadHardwareBuffer))); 171 const ppapi::ContentGamepadHardwareBuffer* buffer = 172 static_cast<const ppapi::ContentGamepadHardwareBuffer*>( 173 shared_memory.memory()); 174 EXPECT_EQ(button_down_data.length, buffer->buffer.length); 175 EXPECT_EQ(button_down_data.items[0].buttonsLength, 176 buffer->buffer.items[0].buttons_length); 177 for (size_t i = 0; i < ppapi::WebKitGamepad::kButtonsLengthCap; i++) { 178 EXPECT_EQ(button_down_data.items[0].buttons[i].value, 179 buffer->buffer.items[0].buttons[i].value); 180 EXPECT_EQ(button_down_data.items[0].buttons[i].pressed, 181 buffer->buffer.items[0].buttons[i].pressed); 182 } 183 184 // Duplicate requests should be denied. 185 EXPECT_EQ(PP_ERROR_FAILED, 186 gamepad_host.OnResourceMessageReceived( 187 PpapiHostMsg_Gamepad_RequestMemory(), &context)); 188} 189 190} // namespace content 191