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 <map>
      6 
      7 #include "base/basictypes.h"
      8 #include "base/compiler_specific.h"
      9 #include "base/logging.h"
     10 #include "content/renderer/pepper/pepper_device_enumeration_host_helper.h"
     11 #include "ppapi/c/pp_errors.h"
     12 #include "ppapi/host/host_message_context.h"
     13 #include "ppapi/host/ppapi_host.h"
     14 #include "ppapi/host/resource_host.h"
     15 #include "ppapi/proxy/ppapi_message_utils.h"
     16 #include "ppapi/proxy/ppapi_messages.h"
     17 #include "ppapi/proxy/resource_message_params.h"
     18 #include "ppapi/proxy/resource_message_test_sink.h"
     19 #include "ppapi/shared_impl/ppapi_permissions.h"
     20 #include "testing/gtest/include/gtest/gtest.h"
     21 #include "url/gurl.h"
     22 
     23 namespace content {
     24 
     25 namespace {
     26 
     27 class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate {
     28  public:
     29   TestDelegate() : last_used_id_(0) {}
     30 
     31   virtual ~TestDelegate() { CHECK(callbacks_.empty()); }
     32 
     33   virtual int EnumerateDevices(PP_DeviceType_Dev /* type */,
     34                                const GURL& /* document_url */,
     35                                const EnumerateDevicesCallback& callback)
     36       OVERRIDE {
     37     last_used_id_++;
     38     callbacks_[last_used_id_] = callback;
     39     return last_used_id_;
     40   }
     41 
     42   virtual void StopEnumerateDevices(int request_id) OVERRIDE {
     43     std::map<int, EnumerateDevicesCallback>::iterator iter =
     44         callbacks_.find(request_id);
     45     CHECK(iter != callbacks_.end());
     46     callbacks_.erase(iter);
     47   }
     48 
     49   // Returns false if |request_id| is not found.
     50   bool SimulateEnumerateResult(
     51       int request_id,
     52       const std::vector<ppapi::DeviceRefData>& devices) {
     53     std::map<int, EnumerateDevicesCallback>::iterator iter =
     54         callbacks_.find(request_id);
     55     if (iter == callbacks_.end())
     56       return false;
     57 
     58     iter->second.Run(request_id, devices);
     59     return true;
     60   }
     61 
     62   size_t GetRegisteredCallbackCount() const { return callbacks_.size(); }
     63 
     64   int last_used_id() const { return last_used_id_; }
     65 
     66  private:
     67   std::map<int, EnumerateDevicesCallback> callbacks_;
     68   int last_used_id_;
     69 
     70   DISALLOW_COPY_AND_ASSIGN(TestDelegate);
     71 };
     72 
     73 class PepperDeviceEnumerationHostHelperTest : public testing::Test {
     74  protected:
     75   PepperDeviceEnumerationHostHelperTest()
     76       : ppapi_host_(&sink_, ppapi::PpapiPermissions()),
     77         resource_host_(&ppapi_host_, 12345, 67890),
     78         device_enumeration_(&resource_host_,
     79                             &delegate_,
     80                             PP_DEVICETYPE_DEV_AUDIOCAPTURE,
     81                             GURL("http://example.com")) {}
     82 
     83   virtual ~PepperDeviceEnumerationHostHelperTest() {}
     84 
     85   void SimulateMonitorDeviceChangeReceived(uint32_t callback_id) {
     86     PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange msg(callback_id);
     87     ppapi::proxy::ResourceMessageCallParams call_params(
     88         resource_host_.pp_resource(), 123);
     89     ppapi::host::HostMessageContext context(call_params);
     90     int32_t result = PP_ERROR_FAILED;
     91     ASSERT_TRUE(
     92         device_enumeration_.HandleResourceMessage(msg, &context, &result));
     93     EXPECT_EQ(PP_OK, result);
     94   }
     95 
     96   void CheckNotifyDeviceChangeMessage(
     97       uint32_t callback_id,
     98       const std::vector<ppapi::DeviceRefData>& expected) {
     99     ppapi::proxy::ResourceMessageReplyParams reply_params;
    100     IPC::Message reply_msg;
    101     ASSERT_TRUE(sink_.GetFirstResourceReplyMatching(
    102         PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange::ID,
    103         &reply_params,
    104         &reply_msg));
    105     sink_.ClearMessages();
    106 
    107     EXPECT_EQ(PP_OK, reply_params.result());
    108 
    109     uint32_t reply_callback_id = 0;
    110     std::vector<ppapi::DeviceRefData> reply_data;
    111     ASSERT_TRUE(ppapi::UnpackMessage<
    112         PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange>(
    113         reply_msg, &reply_callback_id, &reply_data));
    114     EXPECT_EQ(callback_id, reply_callback_id);
    115     EXPECT_EQ(expected, reply_data);
    116   }
    117 
    118   TestDelegate delegate_;
    119   ppapi::proxy::ResourceMessageTestSink sink_;
    120   ppapi::host::PpapiHost ppapi_host_;
    121   ppapi::host::ResourceHost resource_host_;
    122   PepperDeviceEnumerationHostHelper device_enumeration_;
    123 
    124  private:
    125   DISALLOW_COPY_AND_ASSIGN(PepperDeviceEnumerationHostHelperTest);
    126 };
    127 
    128 }  // namespace
    129 
    130 TEST_F(PepperDeviceEnumerationHostHelperTest, EnumerateDevices) {
    131   PpapiHostMsg_DeviceEnumeration_EnumerateDevices msg;
    132   ppapi::proxy::ResourceMessageCallParams call_params(
    133       resource_host_.pp_resource(), 123);
    134   ppapi::host::HostMessageContext context(call_params);
    135   int32_t result = PP_ERROR_FAILED;
    136   ASSERT_TRUE(
    137       device_enumeration_.HandleResourceMessage(msg, &context, &result));
    138   EXPECT_EQ(PP_OK_COMPLETIONPENDING, result);
    139 
    140   EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount());
    141   int request_id = delegate_.last_used_id();
    142 
    143   std::vector<ppapi::DeviceRefData> data;
    144   ppapi::DeviceRefData data_item;
    145   data_item.type = PP_DEVICETYPE_DEV_AUDIOCAPTURE;
    146   data_item.name = "name_1";
    147   data_item.id = "id_1";
    148   data.push_back(data_item);
    149   data_item.type = PP_DEVICETYPE_DEV_VIDEOCAPTURE;
    150   data_item.name = "name_2";
    151   data_item.id = "id_2";
    152   data.push_back(data_item);
    153   ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, data));
    154 
    155   // StopEnumerateDevices() should have been called since the EnumerateDevices
    156   // message is not a persistent request.
    157   EXPECT_EQ(0U, delegate_.GetRegisteredCallbackCount());
    158 
    159   // A reply message should have been sent to the test sink.
    160   ppapi::proxy::ResourceMessageReplyParams reply_params;
    161   IPC::Message reply_msg;
    162   ASSERT_TRUE(sink_.GetFirstResourceReplyMatching(
    163       PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply::ID,
    164       &reply_params,
    165       &reply_msg));
    166 
    167   EXPECT_EQ(call_params.sequence(), reply_params.sequence());
    168   EXPECT_EQ(PP_OK, reply_params.result());
    169 
    170   std::vector<ppapi::DeviceRefData> reply_data;
    171   ASSERT_TRUE(ppapi::UnpackMessage<
    172       PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>(reply_msg,
    173                                                               &reply_data));
    174   EXPECT_EQ(data, reply_data);
    175 }
    176 
    177 TEST_F(PepperDeviceEnumerationHostHelperTest, MonitorDeviceChange) {
    178   uint32_t callback_id = 456;
    179   SimulateMonitorDeviceChangeReceived(callback_id);
    180 
    181   EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount());
    182   int request_id = delegate_.last_used_id();
    183 
    184   std::vector<ppapi::DeviceRefData> data;
    185   ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, data));
    186 
    187   // StopEnumerateDevices() shouldn't be called because the MonitorDeviceChange
    188   // message is a persistent request.
    189   EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount());
    190 
    191   CheckNotifyDeviceChangeMessage(callback_id, data);
    192 
    193   ppapi::DeviceRefData data_item;
    194   data_item.type = PP_DEVICETYPE_DEV_AUDIOCAPTURE;
    195   data_item.name = "name_1";
    196   data_item.id = "id_1";
    197   data.push_back(data_item);
    198   data_item.type = PP_DEVICETYPE_DEV_VIDEOCAPTURE;
    199   data_item.name = "name_2";
    200   data_item.id = "id_2";
    201   data.push_back(data_item);
    202   ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, data));
    203   EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount());
    204 
    205   CheckNotifyDeviceChangeMessage(callback_id, data);
    206 
    207   uint32_t callback_id2 = 789;
    208   SimulateMonitorDeviceChangeReceived(callback_id2);
    209 
    210   // StopEnumerateDevice() should have been called for the previous request.
    211   EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount());
    212   int request_id2 = delegate_.last_used_id();
    213 
    214   data_item.type = PP_DEVICETYPE_DEV_AUDIOCAPTURE;
    215   data_item.name = "name_3";
    216   data_item.id = "id_3";
    217   data.push_back(data_item);
    218   ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id2, data));
    219 
    220   CheckNotifyDeviceChangeMessage(callback_id2, data);
    221 
    222   PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange msg;
    223   ppapi::proxy::ResourceMessageCallParams call_params(
    224       resource_host_.pp_resource(), 123);
    225   ppapi::host::HostMessageContext context(call_params);
    226   int32_t result = PP_ERROR_FAILED;
    227   ASSERT_TRUE(
    228       device_enumeration_.HandleResourceMessage(msg, &context, &result));
    229   EXPECT_EQ(PP_OK, result);
    230 
    231   EXPECT_EQ(0U, delegate_.GetRegisteredCallbackCount());
    232 }
    233 
    234 }  // namespace content
    235