blob: 63a9655c7b7c0b0b9c92f750f32bcd635468cdd9 [file] [log] [blame]
Avi Drissmandb497b32022-09-15 19:47:281// Copyright 2012 The Chromium Authors
[email protected]4f01c762012-12-05 02:44:182// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/proxy/device_enumeration_resource_helper.h"
6
avie029c4132015-12-23 06:45:227#include <stddef.h>
8
dchengced92242016-04-07 00:00:129#include <memory>
10
Hans Wennborg708fa822020-04-27 17:23:1511#include "base/check.h"
Avi Drissman821ca3092023-01-11 22:42:1512#include "base/functional/bind.h"
[email protected]4f01c762012-12-05 02:44:1813#include "ipc/ipc_message.h"
14#include "ipc/ipc_message_macros.h"
15#include "ppapi/c/pp_array_output.h"
16#include "ppapi/c/pp_errors.h"
17#include "ppapi/proxy/dispatch_reply_message.h"
18#include "ppapi/proxy/plugin_resource.h"
19#include "ppapi/proxy/ppapi_messages.h"
20#include "ppapi/proxy/resource_message_params.h"
21#include "ppapi/shared_impl/array_writer.h"
22#include "ppapi/shared_impl/ppapi_globals.h"
23#include "ppapi/shared_impl/ppb_device_ref_shared.h"
24#include "ppapi/shared_impl/proxy_lock.h"
25#include "ppapi/shared_impl/resource_tracker.h"
26#include "ppapi/shared_impl/tracked_callback.h"
27
28namespace ppapi {
29namespace proxy {
30
31DeviceEnumerationResourceHelper::DeviceEnumerationResourceHelper(
32 PluginResource* owner)
33 : owner_(owner),
34 pending_enumerate_devices_(false),
35 monitor_callback_id_(0),
[email protected]4f01c762012-12-05 02:44:1836 monitor_user_data_(NULL) {
37}
38
39DeviceEnumerationResourceHelper::~DeviceEnumerationResourceHelper() {
40}
41
[email protected]4f01c762012-12-05 02:44:1842int32_t DeviceEnumerationResourceHelper::EnumerateDevices(
43 const PP_ArrayOutput& output,
44 scoped_refptr<TrackedCallback> callback) {
45 if (pending_enumerate_devices_)
46 return PP_ERROR_INPROGRESS;
47
48 pending_enumerate_devices_ = true;
49 PpapiHostMsg_DeviceEnumeration_EnumerateDevices msg;
50 owner_->Call<PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>(
51 PluginResource::RENDERER, msg,
Anand K Mistry9182c2a72021-03-17 04:40:0852 base::BindOnce(
[email protected]4f01c762012-12-05 02:44:1853 &DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply,
54 AsWeakPtr(), output, callback));
55 return PP_OK_COMPLETIONPENDING;
56}
57
[email protected]33eccce2012-12-10 22:15:1058int32_t DeviceEnumerationResourceHelper::EnumerateDevicesSync(
59 const PP_ArrayOutput& output) {
60 std::vector<DeviceRefData> devices;
61 int32_t result =
62 owner_->SyncCall<PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>(
63 PluginResource::RENDERER,
64 PpapiHostMsg_DeviceEnumeration_EnumerateDevices(),
65 &devices);
66
67 if (result == PP_OK)
68 result = WriteToArrayOutput(devices, output);
69
70 return result;
71}
72
[email protected]4f01c762012-12-05 02:44:1873int32_t DeviceEnumerationResourceHelper::MonitorDeviceChange(
74 PP_MonitorDeviceChangeCallback callback,
75 void* user_data) {
76 monitor_callback_id_++;
[email protected]4f01c762012-12-05 02:44:1877 monitor_user_data_ = user_data;
[email protected]4f01c762012-12-05 02:44:1878 if (callback) {
[email protected]7ef6b79b2013-01-17 02:38:2479 monitor_callback_.reset(
80 ThreadAwareCallback<PP_MonitorDeviceChangeCallback>::Create(callback));
81 if (!monitor_callback_.get())
82 return PP_ERROR_NO_MESSAGE_LOOP;
83
[email protected]4f01c762012-12-05 02:44:1884 owner_->Post(PluginResource::RENDERER,
85 PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange(
86 monitor_callback_id_));
87 } else {
[email protected]7ef6b79b2013-01-17 02:38:2488 monitor_callback_.reset(NULL);
89
[email protected]4f01c762012-12-05 02:44:1890 owner_->Post(PluginResource::RENDERER,
91 PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange());
92 }
93 return PP_OK;
94}
95
96bool DeviceEnumerationResourceHelper::HandleReply(
97 const ResourceMessageReplyParams& params,
98 const IPC::Message& msg) {
[email protected]dade5f82014-05-13 21:59:2199 PPAPI_BEGIN_MESSAGE_MAP(DeviceEnumerationResourceHelper, msg)
[email protected]4f01c762012-12-05 02:44:18100 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
101 PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange,
102 OnPluginMsgNotifyDeviceChange)
103 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(return false)
[email protected]dade5f82014-05-13 21:59:21104 PPAPI_END_MESSAGE_MAP()
[email protected]4f01c762012-12-05 02:44:18105
106 return true;
107}
108
109void DeviceEnumerationResourceHelper::LastPluginRefWasDeleted() {
110 // Make sure that no further notifications are sent to the plugin.
111 monitor_callback_id_++;
[email protected]7ef6b79b2013-01-17 02:38:24112 monitor_callback_.reset(NULL);
[email protected]4f01c762012-12-05 02:44:18113 monitor_user_data_ = NULL;
114
115 // There is no need to do anything with pending callback of
116 // EnumerateDevices(), because OnPluginMsgEnumerateDevicesReply*() will handle
117 // that properly.
118}
119
[email protected]4f01c762012-12-05 02:44:18120void DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply(
121 const PP_ArrayOutput& output,
122 scoped_refptr<TrackedCallback> callback,
123 const ResourceMessageReplyParams& params,
124 const std::vector<DeviceRefData>& devices) {
125 pending_enumerate_devices_ = false;
126
127 // We shouldn't access |output| if the callback has been called, which is
128 // possible if the last plugin reference to the corresponding resource has
129 // gone away, and the callback has been aborted.
130 if (!TrackedCallback::IsPending(callback))
131 return;
132
133 int32_t result = params.result();
[email protected]33eccce2012-12-10 22:15:10134 if (result == PP_OK)
135 result = WriteToArrayOutput(devices, output);
[email protected]4f01c762012-12-05 02:44:18136
[email protected]33eccce2012-12-10 22:15:10137 callback->Run(result);
[email protected]4f01c762012-12-05 02:44:18138}
139
140void DeviceEnumerationResourceHelper::OnPluginMsgNotifyDeviceChange(
141 const ResourceMessageReplyParams& /* params */,
142 uint32_t callback_id,
143 const std::vector<DeviceRefData>& devices) {
144 if (monitor_callback_id_ != callback_id) {
145 // A new callback or NULL has been set.
146 return;
147 }
148
[email protected]7ef6b79b2013-01-17 02:38:24149 CHECK(monitor_callback_.get());
[email protected]4f01c762012-12-05 02:44:18150
dchengced92242016-04-07 00:00:12151 std::unique_ptr<PP_Resource[]> elements;
brettw669d47b12015-02-13 21:17:38152 uint32_t size = static_cast<uint32_t>(devices.size());
[email protected]4f01c762012-12-05 02:44:18153 if (size > 0) {
154 elements.reset(new PP_Resource[size]);
155 for (size_t index = 0; index < size; ++index) {
156 PPB_DeviceRef_Shared* device_object = new PPB_DeviceRef_Shared(
157 OBJECT_IS_PROXY, owner_->pp_instance(), devices[index]);
158 elements[index] = device_object->GetReference();
159 }
160 }
161
[email protected]7ef6b79b2013-01-17 02:38:24162 monitor_callback_->RunOnTargetThread(monitor_user_data_, size,
163 elements.get());
[email protected]4f01c762012-12-05 02:44:18164 for (size_t index = 0; index < size; ++index)
165 PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(elements[index]);
166}
167
[email protected]33eccce2012-12-10 22:15:10168int32_t DeviceEnumerationResourceHelper::WriteToArrayOutput(
169 const std::vector<DeviceRefData>& devices,
170 const PP_ArrayOutput& output) {
171 ArrayWriter writer(output);
172 if (!writer.is_valid())
173 return PP_ERROR_BADARGUMENT;
174
175 std::vector<scoped_refptr<Resource> > device_resources;
176 for (size_t i = 0; i < devices.size(); ++i) {
177 device_resources.push_back(new PPB_DeviceRef_Shared(
178 OBJECT_IS_PROXY, owner_->pp_instance(), devices[i]));
179 }
180 if (!writer.StoreResourceVector(device_resources))
181 return PP_ERROR_FAILED;
182
183 return PP_OK;
184}
185
[email protected]4f01c762012-12-05 02:44:18186} // namespace proxy
187} // namespace ppapi