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.
5 #include "content/renderer/pepper/pepper_device_enumeration_host_helper.h"
8 #include "base/logging.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "ipc/ipc_message.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/host/dispatch_host_message.h"
14 #include "ppapi/host/host_message_context.h"
15 #include "ppapi/host/ppapi_host.h"
16 #include "ppapi/host/resource_host.h"
17 #include "ppapi/proxy/ppapi_messages.h"
18 #include "ppapi/shared_impl/ppb_device_ref_shared.h"
20 using ppapi::host::HostMessageContext
;
24 // Makes sure that StopEnumerateDevices() is called for each EnumerateDevices().
25 class PepperDeviceEnumerationHostHelper::ScopedRequest
26 : public base::SupportsWeakPtr
<ScopedRequest
> {
28 // |owner| must outlive this object.
29 ScopedRequest(PepperDeviceEnumerationHostHelper
* owner
,
30 const Delegate::EnumerateDevicesCallback
& callback
)
36 if (!owner_
->document_url_
.is_valid())
41 // Note that the callback passed into
42 // PepperDeviceEnumerationHostHelper::Delegate::EnumerateDevices() may be
43 // called synchronously. In that case, |request_id_| hasn't been updated
44 // when the callback is called. Moreover, |callback| may destroy this
45 // object. So we don't pass in |callback| directly. Instead, we use
46 // EnumerateDevicesCallbackBody() to ensure that we always call |callback|
49 DCHECK(owner_
->delegate_
);
50 request_id_
= owner_
->delegate_
->EnumerateDevices(
52 owner_
->document_url_
,
53 base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody
, AsWeakPtr()));
58 if (requested_
&& owner_
->delegate_
) {
59 owner_
->delegate_
->StopEnumerateDevices(request_id_
);
63 bool requested() const { return requested_
; }
66 void EnumerateDevicesCallbackBody(
68 const std::vector
<ppapi::DeviceRefData
>& devices
) {
70 base::MessageLoop::current()->PostTask(
72 base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody
,
77 DCHECK_EQ(request_id_
, request_id
);
78 callback_
.Run(request_id
, devices
);
79 // This object may have been destroyed at this point.
83 PepperDeviceEnumerationHostHelper
* owner_
;
84 PepperDeviceEnumerationHostHelper::Delegate::EnumerateDevicesCallback
90 DISALLOW_COPY_AND_ASSIGN(ScopedRequest
);
93 PepperDeviceEnumerationHostHelper::PepperDeviceEnumerationHostHelper(
94 ppapi::host::ResourceHost
* resource_host
,
95 base::WeakPtr
<Delegate
> delegate
,
96 PP_DeviceType_Dev device_type
,
97 const GURL
& document_url
)
98 : resource_host_(resource_host
),
100 device_type_(device_type
),
101 document_url_(document_url
) {}
103 PepperDeviceEnumerationHostHelper::~PepperDeviceEnumerationHostHelper() {}
105 bool PepperDeviceEnumerationHostHelper::HandleResourceMessage(
106 const IPC::Message
& msg
,
107 HostMessageContext
* context
,
109 bool return_value
= false;
110 *result
= InternalHandleResourceMessage(msg
, context
, &return_value
);
114 int32_t PepperDeviceEnumerationHostHelper::InternalHandleResourceMessage(
115 const IPC::Message
& msg
,
116 HostMessageContext
* context
,
119 PPAPI_BEGIN_MESSAGE_MAP(PepperDeviceEnumerationHostHelper
, msg
)
120 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
121 PpapiHostMsg_DeviceEnumeration_EnumerateDevices
, OnEnumerateDevices
)
122 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
123 PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange
,
124 OnMonitorDeviceChange
)
125 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
126 PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange
,
127 OnStopMonitoringDeviceChange
)
128 PPAPI_END_MESSAGE_MAP()
131 return PP_ERROR_FAILED
;
134 int32_t PepperDeviceEnumerationHostHelper::OnEnumerateDevices(
135 HostMessageContext
* context
) {
136 if (enumerate_devices_context_
.is_valid())
137 return PP_ERROR_INPROGRESS
;
139 enumerate_
.reset(new ScopedRequest(
141 base::Bind(&PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete
,
142 base::Unretained(this))));
143 if (!enumerate_
->requested())
144 return PP_ERROR_FAILED
;
146 enumerate_devices_context_
= context
->MakeReplyMessageContext();
147 return PP_OK_COMPLETIONPENDING
;
150 int32_t PepperDeviceEnumerationHostHelper::OnMonitorDeviceChange(
151 HostMessageContext
* /* context */,
152 uint32_t callback_id
) {
153 monitor_
.reset(new ScopedRequest(
155 base::Bind(&PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange
,
156 base::Unretained(this),
159 return monitor_
->requested() ? PP_OK
: PP_ERROR_FAILED
;
162 int32_t PepperDeviceEnumerationHostHelper::OnStopMonitoringDeviceChange(
163 HostMessageContext
* /* context */) {
164 monitor_
.reset(NULL
);
168 void PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete(
169 int /* request_id */,
170 const std::vector
<ppapi::DeviceRefData
>& devices
) {
171 DCHECK(enumerate_devices_context_
.is_valid());
173 enumerate_
.reset(NULL
);
175 enumerate_devices_context_
.params
.set_result(PP_OK
);
176 resource_host_
->host()->SendReply(
177 enumerate_devices_context_
,
178 PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply(devices
));
179 enumerate_devices_context_
= ppapi::host::ReplyMessageContext();
182 void PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange(
183 uint32_t callback_id
,
184 int /* request_id */,
185 const std::vector
<ppapi::DeviceRefData
>& devices
) {
186 resource_host_
->host()->SendUnsolicitedReply(
187 resource_host_
->pp_resource(),
188 PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange(callback_id
,
192 } // namespace content