1 // Copyright 2016 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.
4
5 #include "content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.h"
6
7 #include "base/bind.h"
8 #include "content/public/browser/browser_task_traits.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "content/public/browser/content_browser_client.h"
11 #include "content/public/browser/pepper_vpn_provider_resource_host_proxy.h"
12 #include "content/public/browser/render_process_host.h"
13 #include "content/public/browser/site_instance.h"
14 #include "content/public/common/content_client.h"
15 #include "ppapi/host/dispatch_host_message.h"
16 #include "ppapi/proxy/ppapi_messages.h"
17
18 namespace {
19
20 // Shared memory buffer configuration.
21 const size_t kMaxBufferedPackets = 128;
22 const size_t kMaxPacketSize = 2048; // 2 KB
23 const size_t kBufferSize = kMaxBufferedPackets * kMaxPacketSize; // 256 KB
24
25 class PepperVpnProviderResourceHostProxyImpl
26 : public content::PepperVpnProviderResourceHostProxy {
27 public:
28 explicit PepperVpnProviderResourceHostProxyImpl(
29 base::WeakPtr<content::PepperVpnProviderMessageFilter>
30 vpn_message_filter);
31
32 void SendOnPacketReceived(const std::vector<char>& packet) override;
33 void SendOnUnbind() override;
34
35 private:
36 base::WeakPtr<content::PepperVpnProviderMessageFilter> vpn_message_filter_;
37
38 DISALLOW_COPY_AND_ASSIGN(PepperVpnProviderResourceHostProxyImpl);
39 };
40
PepperVpnProviderResourceHostProxyImpl(base::WeakPtr<content::PepperVpnProviderMessageFilter> vpn_message_filter)41 PepperVpnProviderResourceHostProxyImpl::PepperVpnProviderResourceHostProxyImpl(
42 base::WeakPtr<content::PepperVpnProviderMessageFilter> vpn_message_filter)
43 : vpn_message_filter_(vpn_message_filter) {}
44
SendOnPacketReceived(const std::vector<char> & packet)45 void PepperVpnProviderResourceHostProxyImpl::SendOnPacketReceived(
46 const std::vector<char>& packet) {
47 if (vpn_message_filter_)
48 vpn_message_filter_->SendOnPacketReceived(packet);
49 }
50
SendOnUnbind()51 void PepperVpnProviderResourceHostProxyImpl::SendOnUnbind() {
52 if (vpn_message_filter_)
53 vpn_message_filter_->SendOnUnbind();
54 }
55
56 } // namespace
57
58 namespace content {
59
PepperVpnProviderMessageFilter(BrowserPpapiHostImpl * host,PP_Instance instance)60 PepperVpnProviderMessageFilter::PepperVpnProviderMessageFilter(
61 BrowserPpapiHostImpl* host,
62 PP_Instance instance)
63 : browser_context_(nullptr), bound_(false) {
64 DCHECK(host);
65
66 document_url_ = host->GetDocumentURLForInstance(instance);
67
68 int render_process_id, unused;
69 bool result =
70 host->GetRenderFrameIDsForInstance(instance, &render_process_id, &unused);
71 DCHECK(result);
72
73 RenderProcessHost* render_process_host =
74 RenderProcessHost::FromID(render_process_id);
75 DCHECK(render_process_host);
76
77 browser_context_ = render_process_host->GetBrowserContext();
78
79 vpn_service_proxy_ =
80 content::GetContentClient()->browser()->GetVpnServiceProxy(
81 browser_context_);
82 }
83
~PepperVpnProviderMessageFilter()84 PepperVpnProviderMessageFilter::~PepperVpnProviderMessageFilter() {
85 if (bound_ && resource_host()) {
86 resource_host()->host()->SendUnsolicitedReply(
87 resource_host()->pp_resource(), PpapiPluginMsg_VpnProvider_OnUnbind());
88 }
89 }
90
91 scoped_refptr<base::SequencedTaskRunner>
OverrideTaskRunnerForMessage(const IPC::Message & message)92 PepperVpnProviderMessageFilter::OverrideTaskRunnerForMessage(
93 const IPC::Message& message) {
94 switch (message.type()) {
95 case PpapiHostMsg_VpnProvider_Bind::ID:
96 case PpapiHostMsg_VpnProvider_SendPacket::ID:
97 case PpapiHostMsg_VpnProvider_OnPacketReceivedReply::ID:
98 return GetUIThreadTaskRunner({});
99 }
100 return nullptr;
101 }
102
OnResourceMessageReceived(const IPC::Message & msg,ppapi::host::HostMessageContext * context)103 int32_t PepperVpnProviderMessageFilter::OnResourceMessageReceived(
104 const IPC::Message& msg,
105 ppapi::host::HostMessageContext* context) {
106 PPAPI_BEGIN_MESSAGE_MAP(PepperVpnProviderMessageFilter, msg)
107 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VpnProvider_Bind, OnBind)
108 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VpnProvider_SendPacket,
109 OnSendPacket)
110 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
111 PpapiHostMsg_VpnProvider_OnPacketReceivedReply, OnPacketReceivedReply)
112 PPAPI_END_MESSAGE_MAP()
113 return PP_ERROR_FAILED;
114 }
115
SendOnPacketReceived(const std::vector<char> & packet)116 void PepperVpnProviderMessageFilter::SendOnPacketReceived(
117 const std::vector<char>& packet) {
118 if (packet.size() == 0 || packet.size() > kMaxPacketSize)
119 return;
120
121 uint32_t id;
122 if (recv_packet_buffer_ && recv_packet_buffer_->GetAvailable(&id)) {
123 recv_packet_buffer_->SetAvailable(id, false);
124 DoPacketReceived(packet, id);
125 } else {
126 received_packets_.push(packet);
127 }
128 }
129
SendOnUnbind()130 void PepperVpnProviderMessageFilter::SendOnUnbind() {
131 configuration_name_.clear();
132 configuration_id_.clear();
133 bound_ = false;
134
135 send_packet_buffer_.reset();
136 recv_packet_buffer_.reset();
137
138 if (resource_host()) {
139 resource_host()->host()->SendUnsolicitedReply(
140 resource_host()->pp_resource(), PpapiPluginMsg_VpnProvider_OnUnbind());
141 }
142 }
143
OnBind(ppapi::host::HostMessageContext * context,const std::string & configuration_id,const std::string & configuration_name)144 int32_t PepperVpnProviderMessageFilter::OnBind(
145 ppapi::host::HostMessageContext* context,
146 const std::string& configuration_id,
147 const std::string& configuration_name) {
148 if (!vpn_service_proxy_)
149 return PP_ERROR_FAILED;
150 if (!content::GetContentClient()->browser()->IsPepperVpnProviderAPIAllowed(
151 browser_context_, document_url_)) {
152 LOG(ERROR) << "Host " << document_url_.host()
153 << " cannot use vpnProvider API";
154 return PP_ERROR_NOACCESS;
155 }
156
157 configuration_id_ = configuration_id;
158 configuration_name_ = configuration_name;
159
160 return DoBind(base::BindOnce(&PepperVpnProviderMessageFilter::OnBindSuccess,
161 weak_factory_.GetWeakPtr(),
162 context->MakeReplyMessageContext()),
163 base::BindOnce(&PepperVpnProviderMessageFilter::OnBindFailure,
164 weak_factory_.GetWeakPtr(),
165 context->MakeReplyMessageContext()));
166 }
167
OnSendPacket(ppapi::host::HostMessageContext * context,uint32_t packet_size,uint32_t id)168 int32_t PepperVpnProviderMessageFilter::OnSendPacket(
169 ppapi::host::HostMessageContext* context,
170 uint32_t packet_size,
171 uint32_t id) {
172 if (!vpn_service_proxy_)
173 return PP_ERROR_FAILED;
174 if (packet_size > kMaxPacketSize)
175 return PP_ERROR_MESSAGE_TOO_BIG;
176
177 char* packet_pointer = static_cast<char*>(send_packet_buffer_->GetBuffer(id));
178 std::vector<char> packet(packet_pointer, packet_pointer + packet_size);
179
180 return DoSendPacket(
181 packet,
182 base::BindOnce(&PepperVpnProviderMessageFilter::OnSendPacketSuccess,
183 weak_factory_.GetWeakPtr(),
184 context->MakeReplyMessageContext(), id),
185 base::BindOnce(&PepperVpnProviderMessageFilter::OnSendPacketFailure,
186 weak_factory_.GetWeakPtr(),
187 context->MakeReplyMessageContext(), id));
188 }
189
OnPacketReceivedReply(ppapi::host::HostMessageContext * context,uint32_t id)190 int32_t PepperVpnProviderMessageFilter::OnPacketReceivedReply(
191 ppapi::host::HostMessageContext* context,
192 uint32_t id) {
193 if (!received_packets_.empty()) {
194 DoPacketReceived(received_packets_.front(), id);
195 received_packets_.pop();
196 } else {
197 recv_packet_buffer_->SetAvailable(id, true);
198 }
199
200 return PP_OK;
201 }
202
DoBind(SuccessCallback success_callback,FailureCallback failure_callback)203 int32_t PepperVpnProviderMessageFilter::DoBind(
204 SuccessCallback success_callback,
205 FailureCallback failure_callback) {
206 // Initialize shared memory
207 if (!send_packet_buffer_ || !recv_packet_buffer_) {
208 base::UnsafeSharedMemoryRegion send_buffer =
209 base::UnsafeSharedMemoryRegion::Create(kBufferSize);
210 base::UnsafeSharedMemoryRegion recv_buffer =
211 base::UnsafeSharedMemoryRegion::Create(kBufferSize);
212 if (!send_buffer.IsValid() || !recv_buffer.IsValid())
213 return PP_ERROR_NOMEMORY;
214
215 base::WritableSharedMemoryMapping send_mapping = send_buffer.Map();
216 base::WritableSharedMemoryMapping recv_mapping = recv_buffer.Map();
217 if (!send_mapping.IsValid() || !recv_mapping.IsValid())
218 return PP_ERROR_NOMEMORY;
219
220 send_packet_buffer_ = std::make_unique<ppapi::VpnProviderSharedBuffer>(
221 kMaxBufferedPackets, kMaxPacketSize, std::move(send_buffer),
222 std::move(send_mapping));
223 recv_packet_buffer_ = std::make_unique<ppapi::VpnProviderSharedBuffer>(
224 kMaxBufferedPackets, kMaxPacketSize, std::move(recv_buffer),
225 std::move(recv_mapping));
226 }
227
228 vpn_service_proxy_->Bind(
229 document_url_.host(), configuration_id_, configuration_name_,
230 std::move(success_callback), std::move(failure_callback),
231 std::make_unique<PepperVpnProviderResourceHostProxyImpl>(
232 weak_factory_.GetWeakPtr()));
233
234 return PP_OK_COMPLETIONPENDING;
235 }
236
OnBindSuccess(const ppapi::host::ReplyMessageContext & context)237 void PepperVpnProviderMessageFilter::OnBindSuccess(
238 const ppapi::host::ReplyMessageContext& context) {
239 bound_ = true;
240
241 context.params.AppendHandle(
242 ppapi::proxy::SerializedHandle(send_packet_buffer_->DuplicateRegion()));
243 context.params.AppendHandle(
244 ppapi::proxy::SerializedHandle(recv_packet_buffer_->DuplicateRegion()));
245
246 OnBindReply(context, PP_OK);
247 }
248
OnBindFailure(const ppapi::host::ReplyMessageContext & context,const std::string & error_name,const std::string & error_message)249 void PepperVpnProviderMessageFilter::OnBindFailure(
250 const ppapi::host::ReplyMessageContext& context,
251 const std::string& error_name,
252 const std::string& error_message) {
253 LOG(ERROR) << "PepperVpnProviderMessageFilter::OnBindFailure(): "
254 << "error_name: "
255 << "\"" << error_name << "\", "
256 << "error_message: "
257 << "\"" << error_message << "\"";
258
259 // Clear buffers on error.
260 send_packet_buffer_.reset();
261 recv_packet_buffer_.reset();
262
263 OnBindReply(context, PP_ERROR_FAILED);
264 }
265
OnBindReply(const ppapi::host::ReplyMessageContext & context,int32_t reply)266 void PepperVpnProviderMessageFilter::OnBindReply(
267 const ppapi::host::ReplyMessageContext& context,
268 int32_t reply) {
269 SendReply(context, PpapiPluginMsg_VpnProvider_BindReply(
270 kMaxBufferedPackets, kMaxPacketSize, reply));
271 }
272
DoSendPacket(const std::vector<char> & packet,SuccessCallback success_callback,FailureCallback failure_callback)273 int32_t PepperVpnProviderMessageFilter::DoSendPacket(
274 const std::vector<char>& packet,
275 SuccessCallback success_callback,
276 FailureCallback failure_callback) {
277 vpn_service_proxy_->SendPacket(document_url_.host(), packet,
278 std::move(success_callback),
279 std::move(failure_callback));
280 return PP_OK_COMPLETIONPENDING;
281 }
282
OnSendPacketSuccess(const ppapi::host::ReplyMessageContext & context,uint32_t id)283 void PepperVpnProviderMessageFilter::OnSendPacketSuccess(
284 const ppapi::host::ReplyMessageContext& context,
285 uint32_t id) {
286 OnSendPacketReply(context, id);
287 }
288
OnSendPacketFailure(const ppapi::host::ReplyMessageContext & context,uint32_t id,const std::string & error_name,const std::string & error_message)289 void PepperVpnProviderMessageFilter::OnSendPacketFailure(
290 const ppapi::host::ReplyMessageContext& context,
291 uint32_t id,
292 const std::string& error_name,
293 const std::string& error_message) {
294 LOG(ERROR) << "PepperVpnProviderMessageFilter::OnSendPacketFailure(): "
295 << "error_name: "
296 << "\"" << error_name << "\", "
297 << "error_message: "
298 << "\"" << error_message << "\"";
299 OnSendPacketReply(context, id);
300 }
301
OnSendPacketReply(const ppapi::host::ReplyMessageContext & context,uint32_t id)302 void PepperVpnProviderMessageFilter::OnSendPacketReply(
303 const ppapi::host::ReplyMessageContext& context,
304 uint32_t id) {
305 SendReply(context, PpapiPluginMsg_VpnProvider_SendPacketReply(id));
306 }
307
DoPacketReceived(const std::vector<char> & packet,uint32_t id)308 void PepperVpnProviderMessageFilter::DoPacketReceived(
309 const std::vector<char>& packet,
310 uint32_t id) {
311 uint32_t packet_size = base::checked_cast<uint32_t>(packet.size());
312 DCHECK_GT(packet_size, 0U);
313
314 const void* packet_pointer = &packet.front();
315 memcpy(recv_packet_buffer_->GetBuffer(id), packet_pointer, packet_size);
316
317 if (resource_host()) {
318 resource_host()->host()->SendUnsolicitedReply(
319 resource_host()->pp_resource(),
320 PpapiPluginMsg_VpnProvider_OnPacketReceived(packet_size, id));
321 }
322 }
323
324 } // namespace content
325