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