| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <map> |
| |
| #include "base/compiler_specific.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/run_loop.h" |
| #include "base/test/scoped_task_environment.h" |
| #include "content/renderer/pepper/pepper_device_enumeration_host_helper.h" |
| #include "ppapi/c/pp_errors.h" |
| #include "ppapi/host/host_message_context.h" |
| #include "ppapi/host/ppapi_host.h" |
| #include "ppapi/host/resource_host.h" |
| #include "ppapi/proxy/ppapi_message_utils.h" |
| #include "ppapi/proxy/ppapi_messages.h" |
| #include "ppapi/proxy/resource_message_params.h" |
| #include "ppapi/proxy/resource_message_test_sink.h" |
| #include "ppapi/shared_impl/ppapi_permissions.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| std::vector<ppapi::DeviceRefData> TestEnumerationData() { |
| std::vector<ppapi::DeviceRefData> data; |
| ppapi::DeviceRefData data_item; |
| data_item.type = PP_DEVICETYPE_DEV_AUDIOCAPTURE; |
| data_item.name = "name_1"; |
| data_item.id = "id_1"; |
| data.push_back(data_item); |
| data_item.type = PP_DEVICETYPE_DEV_VIDEOCAPTURE; |
| data_item.name = "name_2"; |
| data_item.id = "id_2"; |
| data.push_back(data_item); |
| |
| return data; |
| } |
| |
| class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate, |
| public base::SupportsWeakPtr<TestDelegate> { |
| public: |
| TestDelegate() : last_used_id_(0u) {} |
| |
| ~TestDelegate() override { CHECK(monitoring_callbacks_.empty()); } |
| |
| void EnumerateDevices(PP_DeviceType_Dev /* type */, |
| const DevicesCallback& callback) override { |
| callback.Run(TestEnumerationData()); |
| } |
| |
| size_t StartMonitoringDevices(PP_DeviceType_Dev /* type */, |
| const DevicesCallback& callback) override { |
| last_used_id_++; |
| monitoring_callbacks_[last_used_id_] = callback; |
| return last_used_id_; |
| } |
| |
| void StopMonitoringDevices(PP_DeviceType_Dev /* type */, |
| size_t subscription_id) override { |
| auto iter = monitoring_callbacks_.find(subscription_id); |
| CHECK(iter != monitoring_callbacks_.end()); |
| monitoring_callbacks_.erase(iter); |
| } |
| |
| // Returns false if |request_id| is not found. |
| bool SimulateDevicesChanged( |
| size_t subscription_id, |
| const std::vector<ppapi::DeviceRefData>& devices) { |
| auto iter = monitoring_callbacks_.find(subscription_id); |
| if (iter == monitoring_callbacks_.end()) |
| return false; |
| |
| iter->second.Run(devices); |
| return true; |
| } |
| |
| size_t GetRegisteredCallbackCount() const { |
| return monitoring_callbacks_.size(); |
| } |
| |
| size_t last_used_id() const { return last_used_id_; } |
| |
| private: |
| std::map<size_t, DevicesCallback> monitoring_callbacks_; |
| size_t last_used_id_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestDelegate); |
| }; |
| |
| class PepperDeviceEnumerationHostHelperTest : public testing::Test { |
| protected: |
| PepperDeviceEnumerationHostHelperTest() |
| : ppapi_host_(&sink_, ppapi::PpapiPermissions()), |
| resource_host_(&ppapi_host_, 12345, 67890), |
| device_enumeration_(&resource_host_, |
| delegate_.AsWeakPtr(), |
| PP_DEVICETYPE_DEV_AUDIOCAPTURE, |
| GURL("http://example.com")) {} |
| |
| ~PepperDeviceEnumerationHostHelperTest() override {} |
| |
| void SimulateMonitorDeviceChangeReceived(uint32_t callback_id) { |
| PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange msg(callback_id); |
| ppapi::proxy::ResourceMessageCallParams call_params( |
| resource_host_.pp_resource(), 123); |
| ppapi::host::HostMessageContext context(call_params); |
| int32_t result = PP_ERROR_FAILED; |
| ASSERT_TRUE( |
| device_enumeration_.HandleResourceMessage(msg, &context, &result)); |
| EXPECT_EQ(PP_OK, result); |
| } |
| |
| void CheckNotifyDeviceChangeMessage( |
| uint32_t callback_id, |
| const std::vector<ppapi::DeviceRefData>& expected) { |
| ppapi::proxy::ResourceMessageReplyParams reply_params; |
| IPC::Message reply_msg; |
| ASSERT_TRUE(sink_.GetFirstResourceReplyMatching( |
| PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange::ID, |
| &reply_params, |
| &reply_msg)); |
| sink_.ClearMessages(); |
| |
| EXPECT_EQ(PP_OK, reply_params.result()); |
| |
| uint32_t reply_callback_id = 0; |
| std::vector<ppapi::DeviceRefData> reply_data; |
| ASSERT_TRUE(ppapi::UnpackMessage< |
| PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange>( |
| reply_msg, &reply_callback_id, &reply_data)); |
| EXPECT_EQ(callback_id, reply_callback_id); |
| EXPECT_EQ(expected, reply_data); |
| } |
| |
| TestDelegate delegate_; |
| ppapi::proxy::ResourceMessageTestSink sink_; |
| ppapi::host::PpapiHost ppapi_host_; |
| ppapi::host::ResourceHost resource_host_; |
| PepperDeviceEnumerationHostHelper device_enumeration_; |
| base::test::ScopedTaskEnvironment |
| task_environment_; // required for async calls to work. |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(PepperDeviceEnumerationHostHelperTest); |
| }; |
| |
| } // namespace |
| |
| TEST_F(PepperDeviceEnumerationHostHelperTest, EnumerateDevices) { |
| PpapiHostMsg_DeviceEnumeration_EnumerateDevices msg; |
| ppapi::proxy::ResourceMessageCallParams call_params( |
| resource_host_.pp_resource(), 123); |
| ppapi::host::HostMessageContext context(call_params); |
| int32_t result = PP_ERROR_FAILED; |
| ASSERT_TRUE( |
| device_enumeration_.HandleResourceMessage(msg, &context, &result)); |
| EXPECT_EQ(PP_OK_COMPLETIONPENDING, result); |
| base::RunLoop().RunUntilIdle(); |
| |
| // A reply message should have been sent to the test sink. |
| ppapi::proxy::ResourceMessageReplyParams reply_params; |
| IPC::Message reply_msg; |
| ASSERT_TRUE(sink_.GetFirstResourceReplyMatching( |
| PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply::ID, |
| &reply_params, |
| &reply_msg)); |
| |
| EXPECT_EQ(call_params.sequence(), reply_params.sequence()); |
| EXPECT_EQ(PP_OK, reply_params.result()); |
| |
| std::vector<ppapi::DeviceRefData> reply_data; |
| ASSERT_TRUE(ppapi::UnpackMessage< |
| PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>(reply_msg, |
| &reply_data)); |
| EXPECT_EQ(TestEnumerationData(), reply_data); |
| } |
| |
| TEST_F(PepperDeviceEnumerationHostHelperTest, MonitorDeviceChange) { |
| uint32_t callback_id = 456; |
| SimulateMonitorDeviceChangeReceived(callback_id); |
| |
| EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount()); |
| size_t request_id = delegate_.last_used_id(); |
| |
| std::vector<ppapi::DeviceRefData> data; |
| ASSERT_TRUE(delegate_.SimulateDevicesChanged(request_id, data)); |
| |
| // StopEnumerateDevices() shouldn't be called because the MonitorDeviceChange |
| // message is a persistent request. |
| EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount()); |
| |
| CheckNotifyDeviceChangeMessage(callback_id, data); |
| |
| ppapi::DeviceRefData data_item; |
| data_item.type = PP_DEVICETYPE_DEV_AUDIOCAPTURE; |
| data_item.name = "name_1"; |
| data_item.id = "id_1"; |
| data.push_back(data_item); |
| data_item.type = PP_DEVICETYPE_DEV_VIDEOCAPTURE; |
| data_item.name = "name_2"; |
| data_item.id = "id_2"; |
| data.push_back(data_item); |
| ASSERT_TRUE(delegate_.SimulateDevicesChanged(request_id, data)); |
| EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount()); |
| |
| CheckNotifyDeviceChangeMessage(callback_id, data); |
| |
| uint32_t callback_id2 = 789; |
| SimulateMonitorDeviceChangeReceived(callback_id2); |
| |
| // StopEnumerateDevice() should have been called for the previous request. |
| EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount()); |
| size_t request_id2 = delegate_.last_used_id(); |
| |
| data_item.type = PP_DEVICETYPE_DEV_AUDIOCAPTURE; |
| data_item.name = "name_3"; |
| data_item.id = "id_3"; |
| data.push_back(data_item); |
| ASSERT_TRUE(delegate_.SimulateDevicesChanged(request_id2, data)); |
| |
| CheckNotifyDeviceChangeMessage(callback_id2, data); |
| |
| PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange msg; |
| ppapi::proxy::ResourceMessageCallParams call_params( |
| resource_host_.pp_resource(), 123); |
| ppapi::host::HostMessageContext context(call_params); |
| int32_t result = PP_ERROR_FAILED; |
| ASSERT_TRUE( |
| device_enumeration_.HandleResourceMessage(msg, &context, &result)); |
| EXPECT_EQ(PP_OK, result); |
| |
| EXPECT_EQ(0U, delegate_.GetRegisteredCallbackCount()); |
| } |
| |
| } // namespace content |