[M108 Aura Migration][NaCl][PPFwk] Add error logs + SVACE/DLOG/Static analysis fix
[platform/framework/web/chromium-efl.git] / content / renderer / pepper / pepper_device_enumeration_host_helper.cc
1 // Copyright 2012 The Chromium Authors
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 "content/renderer/pepper/pepper_device_enumeration_host_helper.h"
6
7 #include "base/bind.h"
8 #include "base/check.h"
9 #include "base/location.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/task/single_thread_task_runner.h"
12 #include "base/threading/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"
21
22 using ppapi::host::HostMessageContext;
23
24 namespace content {
25
26 // Makes sure that StopEnumerateDevices() is called for each EnumerateDevices().
27 class PepperDeviceEnumerationHostHelper::ScopedEnumerationRequest
28     : public base::SupportsWeakPtr<ScopedEnumerationRequest> {
29  public:
30   // |owner| must outlive this object.
31   ScopedEnumerationRequest(PepperDeviceEnumerationHostHelper* owner,
32                            Delegate::DevicesOnceCallback callback)
33       : callback_(std::move(callback)), requested_(false), sync_call_(false) {
34     if (!owner->delegate_) {
35       // If no delegate, return an empty list of devices.
36       base::ThreadTaskRunnerHandle::Get()->PostTask(
37           FROM_HERE,
38           base::BindOnce(
39               &ScopedEnumerationRequest::EnumerateDevicesCallbackBody,
40               AsWeakPtr(), std::vector<ppapi::DeviceRefData>()));
41       return;
42     }
43
44     requested_ = true;
45
46     // Note that the callback passed into
47     // PepperDeviceEnumerationHostHelper::Delegate::EnumerateDevices() may be
48     // called synchronously. In that case, |callback| may destroy this
49     // object. So we don't pass in |callback| directly. Instead, we use
50     // EnumerateDevicesCallbackBody() to ensure that we always call |callback|
51     // asynchronously.
52     sync_call_ = true;
53     owner->delegate_->EnumerateDevices(
54         owner->device_type_,
55         base::BindOnce(&ScopedEnumerationRequest::EnumerateDevicesCallbackBody,
56                        AsWeakPtr()));
57     sync_call_ = false;
58   }
59
60   ScopedEnumerationRequest(const ScopedEnumerationRequest&) = delete;
61   ScopedEnumerationRequest& operator=(const ScopedEnumerationRequest&) = delete;
62
63   bool requested() const { return requested_; }
64
65  private:
66   void EnumerateDevicesCallbackBody(
67       const std::vector<ppapi::DeviceRefData>& devices) {
68     if (sync_call_) {
69       base::ThreadTaskRunnerHandle::Get()->PostTask(
70           FROM_HERE,
71           base::BindOnce(
72               &ScopedEnumerationRequest::EnumerateDevicesCallbackBody,
73               AsWeakPtr(), devices));
74     } else {
75       std::move(callback_).Run(devices);
76       // This object may have been destroyed at this point.
77     }
78   }
79
80   PepperDeviceEnumerationHostHelper::Delegate::DevicesOnceCallback callback_;
81   bool requested_;
82   bool sync_call_;
83 };
84
85 // Makes sure that StopMonitoringDevices() is called for each
86 // StartMonitoringDevices().
87 class PepperDeviceEnumerationHostHelper::ScopedMonitoringRequest
88     : public base::SupportsWeakPtr<ScopedMonitoringRequest> {
89  public:
90   // |owner| must outlive this object.
91   ScopedMonitoringRequest(PepperDeviceEnumerationHostHelper* owner,
92                           Delegate::DevicesCallback callback)
93       : owner_(owner),
94         callback_(std::move(callback)),
95         requested_(false),
96         subscription_id_(0u) {
97     DCHECK(owner_);
98     if (!owner->delegate_) {
99       return;
100     }
101
102     requested_ = true;
103
104     // |callback| is never called synchronously by StartMonitoringDevices(),
105     // so it is OK to pass it directly, even if |callback| destroys |this|.
106     subscription_id_ = owner_->delegate_->StartMonitoringDevices(
107         owner_->device_type_, callback_);
108   }
109
110   ScopedMonitoringRequest(const ScopedMonitoringRequest&) = delete;
111   ScopedMonitoringRequest& operator=(const ScopedMonitoringRequest&) = delete;
112
113   ~ScopedMonitoringRequest() {
114     if (requested_ && owner_->delegate_) {
115       owner_->delegate_->StopMonitoringDevices(owner_->device_type_,
116                                                subscription_id_);
117     }
118   }
119
120   bool requested() const { return requested_; }
121
122  private:
123   PepperDeviceEnumerationHostHelper* const owner_;
124   PepperDeviceEnumerationHostHelper::Delegate::DevicesCallback callback_;
125   bool requested_;
126   size_t subscription_id_;
127 };
128
129 PepperDeviceEnumerationHostHelper::PepperDeviceEnumerationHostHelper(
130     ppapi::host::ResourceHost* resource_host,
131     base::WeakPtr<Delegate> delegate,
132     PP_DeviceType_Dev device_type,
133     const GURL& document_url)
134     : resource_host_(resource_host),
135       delegate_(delegate),
136       device_type_(device_type) {}
137
138 PepperDeviceEnumerationHostHelper::~PepperDeviceEnumerationHostHelper() {}
139
140 bool PepperDeviceEnumerationHostHelper::HandleResourceMessage(
141     const IPC::Message& msg,
142     HostMessageContext* context,
143     int32_t* result) {
144   bool return_value = false;
145   *result = InternalHandleResourceMessage(msg, context, &return_value);
146   return return_value;
147 }
148
149 int32_t PepperDeviceEnumerationHostHelper::InternalHandleResourceMessage(
150     const IPC::Message& msg,
151     HostMessageContext* context,
152     bool* handled) {
153   *handled = true;
154   PPAPI_BEGIN_MESSAGE_MAP(PepperDeviceEnumerationHostHelper, msg)
155     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
156         PpapiHostMsg_DeviceEnumeration_EnumerateDevices, OnEnumerateDevices)
157     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
158         PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange,
159         OnMonitorDeviceChange)
160     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
161         PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange,
162         OnStopMonitoringDeviceChange)
163   PPAPI_END_MESSAGE_MAP()
164
165   *handled = false;
166   LOG(ERROR) << "Cannot handle internal resource message";
167   return PP_ERROR_FAILED;
168 }
169
170 int32_t PepperDeviceEnumerationHostHelper::OnEnumerateDevices(
171     HostMessageContext* context) {
172   if (enumerate_devices_context_.is_valid()) {
173     LOG(ERROR) << "Invalid enumerate devices context";
174     return PP_ERROR_INPROGRESS;
175   }
176
177   enumerate_ = std::make_unique<ScopedEnumerationRequest>(
178       this, base::BindOnce(
179                 &PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete,
180                 base::Unretained(this)));
181   if (!enumerate_->requested()) {
182     LOG(ERROR) << "Cannot request enumerate";
183     return PP_ERROR_FAILED;
184   }
185
186   enumerate_devices_context_ = context->MakeReplyMessageContext();
187   return PP_OK_COMPLETIONPENDING;
188 }
189
190 int32_t PepperDeviceEnumerationHostHelper::OnMonitorDeviceChange(
191     HostMessageContext* /* context */,
192     uint32_t callback_id) {
193   monitor_ = std::make_unique<ScopedMonitoringRequest>(
194       this, base::BindRepeating(
195                 &PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange,
196                 base::Unretained(this), callback_id));
197
198   return monitor_->requested() ? PP_OK : PP_ERROR_FAILED;
199 }
200
201 int32_t PepperDeviceEnumerationHostHelper::OnStopMonitoringDeviceChange(
202     HostMessageContext* /* context */) {
203   monitor_.reset(nullptr);
204   return PP_OK;
205 }
206
207 void PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete(
208     const std::vector<ppapi::DeviceRefData>& devices) {
209   DCHECK(enumerate_devices_context_.is_valid());
210
211   enumerate_.reset(nullptr);
212
213   enumerate_devices_context_.params.set_result(PP_OK);
214   resource_host_->host()->SendReply(
215       enumerate_devices_context_,
216       PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply(devices));
217   enumerate_devices_context_ = ppapi::host::ReplyMessageContext();
218 }
219
220 void PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange(
221     uint32_t callback_id,
222     const std::vector<ppapi::DeviceRefData>& devices) {
223   resource_host_->host()->SendUnsolicitedReply(
224       resource_host_->pp_resource(),
225       PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange(callback_id,
226                                                           devices));
227 }
228
229 }  // namespace content