Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / renderer / pepper / pepper_device_enumeration_host_helper.cc
blob8429d88345817f50b232a80199c1a10f219b18d0
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"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "ipc/ipc_message.h"
14 #include "ppapi/c/pp_errors.h"
15 #include "ppapi/host/dispatch_host_message.h"
16 #include "ppapi/host/host_message_context.h"
17 #include "ppapi/host/ppapi_host.h"
18 #include "ppapi/host/resource_host.h"
19 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/shared_impl/ppb_device_ref_shared.h"
22 using ppapi::host::HostMessageContext;
24 namespace content {
26 // Makes sure that StopEnumerateDevices() is called for each EnumerateDevices().
27 class PepperDeviceEnumerationHostHelper::ScopedRequest
28 : public base::SupportsWeakPtr<ScopedRequest> {
29 public:
30 // |owner| must outlive this object.
31 ScopedRequest(PepperDeviceEnumerationHostHelper* owner,
32 const Delegate::EnumerateDevicesCallback& callback)
33 : owner_(owner),
34 callback_(callback),
35 requested_(false),
36 request_id_(0),
37 sync_call_(false) {
38 if (!owner_->document_url_.is_valid())
39 return;
41 requested_ = true;
43 // Note that the callback passed into
44 // PepperDeviceEnumerationHostHelper::Delegate::EnumerateDevices() may be
45 // called synchronously. In that case, |request_id_| hasn't been updated
46 // when the callback is called. Moreover, |callback| may destroy this
47 // object. So we don't pass in |callback| directly. Instead, we use
48 // EnumerateDevicesCallbackBody() to ensure that we always call |callback|
49 // asynchronously.
50 sync_call_ = true;
51 DCHECK(owner_->delegate_);
52 request_id_ = owner_->delegate_->EnumerateDevices(
53 owner_->device_type_,
54 owner_->document_url_,
55 base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody, AsWeakPtr()));
56 sync_call_ = false;
59 ~ScopedRequest() {
60 if (requested_ && owner_->delegate_) {
61 owner_->delegate_->StopEnumerateDevices(request_id_);
65 bool requested() const { return requested_; }
67 private:
68 void EnumerateDevicesCallbackBody(
69 int request_id,
70 const std::vector<ppapi::DeviceRefData>& devices) {
71 if (sync_call_) {
72 base::ThreadTaskRunnerHandle::Get()->PostTask(
73 FROM_HERE, base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody,
74 AsWeakPtr(), request_id, devices));
75 } else {
76 DCHECK_EQ(request_id_, request_id);
77 callback_.Run(request_id, devices);
78 // This object may have been destroyed at this point.
82 PepperDeviceEnumerationHostHelper* owner_;
83 PepperDeviceEnumerationHostHelper::Delegate::EnumerateDevicesCallback
84 callback_;
85 bool requested_;
86 int request_id_;
87 bool sync_call_;
89 DISALLOW_COPY_AND_ASSIGN(ScopedRequest);
92 PepperDeviceEnumerationHostHelper::PepperDeviceEnumerationHostHelper(
93 ppapi::host::ResourceHost* resource_host,
94 base::WeakPtr<Delegate> delegate,
95 PP_DeviceType_Dev device_type,
96 const GURL& document_url)
97 : resource_host_(resource_host),
98 delegate_(delegate),
99 device_type_(device_type),
100 document_url_(document_url) {}
102 PepperDeviceEnumerationHostHelper::~PepperDeviceEnumerationHostHelper() {}
104 bool PepperDeviceEnumerationHostHelper::HandleResourceMessage(
105 const IPC::Message& msg,
106 HostMessageContext* context,
107 int32_t* result) {
108 bool return_value = false;
109 *result = InternalHandleResourceMessage(msg, context, &return_value);
110 return return_value;
113 int32_t PepperDeviceEnumerationHostHelper::InternalHandleResourceMessage(
114 const IPC::Message& msg,
115 HostMessageContext* context,
116 bool* handled) {
117 *handled = true;
118 PPAPI_BEGIN_MESSAGE_MAP(PepperDeviceEnumerationHostHelper, msg)
119 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
120 PpapiHostMsg_DeviceEnumeration_EnumerateDevices, OnEnumerateDevices)
121 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
122 PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange,
123 OnMonitorDeviceChange)
124 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
125 PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange,
126 OnStopMonitoringDeviceChange)
127 PPAPI_END_MESSAGE_MAP()
129 *handled = false;
130 return PP_ERROR_FAILED;
133 int32_t PepperDeviceEnumerationHostHelper::OnEnumerateDevices(
134 HostMessageContext* context) {
135 if (enumerate_devices_context_.is_valid())
136 return PP_ERROR_INPROGRESS;
138 enumerate_.reset(new ScopedRequest(
139 this,
140 base::Bind(&PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete,
141 base::Unretained(this))));
142 if (!enumerate_->requested())
143 return PP_ERROR_FAILED;
145 enumerate_devices_context_ = context->MakeReplyMessageContext();
146 return PP_OK_COMPLETIONPENDING;
149 int32_t PepperDeviceEnumerationHostHelper::OnMonitorDeviceChange(
150 HostMessageContext* /* context */,
151 uint32_t callback_id) {
152 monitor_.reset(new ScopedRequest(
153 this,
154 base::Bind(&PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange,
155 base::Unretained(this),
156 callback_id)));
158 return monitor_->requested() ? PP_OK : PP_ERROR_FAILED;
161 int32_t PepperDeviceEnumerationHostHelper::OnStopMonitoringDeviceChange(
162 HostMessageContext* /* context */) {
163 monitor_.reset(NULL);
164 return PP_OK;
167 void PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete(
168 int /* request_id */,
169 const std::vector<ppapi::DeviceRefData>& devices) {
170 DCHECK(enumerate_devices_context_.is_valid());
172 enumerate_.reset(NULL);
174 enumerate_devices_context_.params.set_result(PP_OK);
175 resource_host_->host()->SendReply(
176 enumerate_devices_context_,
177 PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply(devices));
178 enumerate_devices_context_ = ppapi::host::ReplyMessageContext();
181 void PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange(
182 uint32_t callback_id,
183 int /* request_id */,
184 const std::vector<ppapi::DeviceRefData>& devices) {
185 resource_host_->host()->SendUnsolicitedReply(
186 resource_host_->pp_resource(),
187 PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange(callback_id,
188 devices));
191 } // namespace content