Chromium Code Reviews| Index: content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc |
| diff --git a/content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc b/content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b3363e0fde46b6b701ab76d39a87de3bdf95a0a4 |
| --- /dev/null |
| +++ b/content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc |
| @@ -0,0 +1,321 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.h" |
| + |
| +#include "base/memory/ptr_util.h" |
| +#include "content/public/browser/browser_ppapi_host.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/content_browser_client.h" |
| +#include "content/public/browser/pepper_vpn_provider_resource_host_proxy.h" |
| +#include "content/public/browser/render_process_host.h" |
| +#include "content/public/browser/site_instance.h" |
| +#include "content/public/common/content_client.h" |
| +#include "ppapi/host/dispatch_host_message.h" |
| +#include "ppapi/host/host_message_context.h" |
| +#include "ppapi/proxy/ppapi_messages.h" |
| + |
| +namespace { |
| + |
| +// Shared memory buffer configuration. |
| +const size_t kMaxQueuedPackets = 128; |
| +const size_t kMaxPacketSizeInBytes = 2048; // 2 KB |
| +const size_t kBufferSize = kMaxQueuedPackets * kMaxPacketSizeInBytes; // 256 KB |
| + |
| +} // namespace |
| + |
| +namespace content { |
| + |
| +class PepperVpnProviderMessageFilter::PepperVpnProviderResourceHostProxyImpl |
|
bbudge
2016/06/23 18:10:22
Standalone class in anonymous namespace.
adrian.belgun
2016/06/24 13:19:37
Done.
|
| + : public content::PepperVpnProviderResourceHostProxy { |
| + public: |
| + PepperVpnProviderResourceHostProxyImpl( |
| + base::WeakPtr<PepperVpnProviderMessageFilter> vpn_message_filter); |
| + ~PepperVpnProviderResourceHostProxyImpl() override; |
| + |
| + void SendOnPacketReceived(const std::vector<char>& packet) override; |
| + void SendOnUnbind() override; |
| + |
| + private: |
| + base::WeakPtr<PepperVpnProviderMessageFilter> vpn_message_filter_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PepperVpnProviderResourceHostProxyImpl); |
| +}; |
| + |
| +PepperVpnProviderMessageFilter::PepperVpnProviderResourceHostProxyImpl:: |
| + PepperVpnProviderResourceHostProxyImpl( |
| + base::WeakPtr<PepperVpnProviderMessageFilter> vpn_message_filter) |
| + : vpn_message_filter_(vpn_message_filter) {} |
| + |
| +PepperVpnProviderMessageFilter::PepperVpnProviderResourceHostProxyImpl:: |
| + ~PepperVpnProviderResourceHostProxyImpl() {} |
| + |
| +void PepperVpnProviderMessageFilter::PepperVpnProviderResourceHostProxyImpl:: |
| + SendOnPacketReceived(const std::vector<char>& packet) { |
| + if (!vpn_message_filter_) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + vpn_message_filter_->SendOnPacketReceived(packet); |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::PepperVpnProviderResourceHostProxyImpl:: |
| + SendOnUnbind() { |
| + if (!vpn_message_filter_) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + vpn_message_filter_->SendOnUnbind(); |
| +} |
| + |
| +PepperVpnProviderMessageFilter::PepperVpnProviderMessageFilter( |
| + BrowserPpapiHostImpl* host, |
| + PP_Instance instance) |
| + : browser_context_(nullptr), bound_(false), weak_factory_(this) { |
| + DCHECK(host); |
| + |
| + int render_process_id; |
| + int render_frame_id; |
| + if (!host->GetRenderFrameIDsForInstance(instance, &render_process_id, |
| + &render_frame_id)) { |
| + NOTREACHED(); |
|
bbudge
2016/06/23 18:10:22
return here.
adrian.belgun
2016/06/24 13:19:37
Done.
|
| + } |
| + |
| + extension_id_ = host->GetDocumentURLForInstance(instance); |
|
bbudge
2016/06/23 18:10:22
This should be named document_url_ as it's not rea
adrian.belgun
2016/06/24 13:19:37
Done.
|
| + |
| + RenderProcessHost* render_process_host = |
| + RenderProcessHost::FromID(render_process_id); |
| + if (render_process_host) |
| + browser_context_ = render_process_host->GetBrowserContext(); |
| + |
| + if (browser_context_) { |
| + vpn_service_proxy_ = |
| + content::GetContentClient()->browser()->GetVpnServiceProxy( |
| + browser_context_); |
| + } |
| +} |
| + |
| +PepperVpnProviderMessageFilter::~PepperVpnProviderMessageFilter() { |
| + if (bound_ && resource_host()) { |
| + resource_host()->host()->SendUnsolicitedReply( |
| + resource_host()->pp_resource(), PpapiPluginMsg_VpnProvider_OnUnbind()); |
| + } |
| +} |
| + |
| +scoped_refptr<base::TaskRunner> |
| +PepperVpnProviderMessageFilter::OverrideTaskRunnerForMessage( |
| + const IPC::Message& message) { |
| + switch (message.type()) { |
| + case PpapiHostMsg_VpnProvider_Bind::ID: |
| + case PpapiHostMsg_VpnProvider_SendPacket::ID: |
| + case PpapiHostMsg_VpnProvider_OnPacketReceivedReply::ID: |
| + return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); |
| + } |
| + return NULL; |
| +} |
| + |
| +int32_t PepperVpnProviderMessageFilter::OnResourceMessageReceived( |
| + const IPC::Message& msg, |
| + ppapi::host::HostMessageContext* context) { |
| + PPAPI_BEGIN_MESSAGE_MAP(PepperVpnProviderMessageFilter, msg) |
| + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VpnProvider_Bind, OnBind) |
| + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VpnProvider_SendPacket, |
| + OnSendPacket) |
| + PPAPI_DISPATCH_HOST_RESOURCE_CALL( |
| + PpapiHostMsg_VpnProvider_OnPacketReceivedReply, OnPacketReceivedReply) |
| + PPAPI_END_MESSAGE_MAP() |
| + return PP_ERROR_FAILED; |
| +} |
| + |
| +int32_t PepperVpnProviderMessageFilter::OnBind( |
| + ppapi::host::HostMessageContext* context, |
| + const std::string& configuration_id, |
| + const std::string& configuration_name) { |
|
bbudge
2016/06/23 18:10:22
Is it OK to call Bind multiple times? It seems und
adrian.belgun
2016/06/24 13:19:37
Yes it is. It's expected behavior for supporting r
|
| + if (!vpn_service_proxy_) |
| + return PP_ERROR_FAILED; |
| + if (!content::GetContentClient()->browser()->IsPepperVpnProviderAPIAllowed( |
| + browser_context_, extension_id_)) { |
| + LOG(ERROR) << "Host " << extension_id_.host() |
| + << " cannot use vpnProvider API"; |
| + return PP_ERROR_NOACCESS; |
| + } |
| + |
| + configuration_id_ = configuration_id; |
| + configuration_name_ = configuration_name; |
| + |
| + return DoBind(base::Bind(&PepperVpnProviderMessageFilter::OnBindSuccess, |
| + weak_factory_.GetWeakPtr(), |
| + context->MakeReplyMessageContext()), |
| + base::Bind(&PepperVpnProviderMessageFilter::OnBindFailure, |
| + weak_factory_.GetWeakPtr(), |
| + context->MakeReplyMessageContext())); |
| +} |
| + |
| +int32_t PepperVpnProviderMessageFilter::OnSendPacket( |
| + ppapi::host::HostMessageContext* context, |
| + uint32_t packet_size, |
| + uint32_t id) { |
| + if (!vpn_service_proxy_) |
| + return PP_ERROR_FAILED; |
| + if (packet_size > kMaxPacketSizeInBytes) |
| + return PP_ERROR_MESSAGE_TOO_BIG; |
| + |
| + char* packet_pointer = static_cast<char*>(send_packet_buffer_->GetBuffer(id)); |
| + std::vector<char> packet(packet_pointer, packet_pointer + packet_size); |
| + |
| + return DoSendPacket( |
| + packet, base::Bind(&PepperVpnProviderMessageFilter::OnSendPacketSuccess, |
| + weak_factory_.GetWeakPtr(), |
| + context->MakeReplyMessageContext(), id), |
| + base::Bind(&PepperVpnProviderMessageFilter::OnSendPacketFailure, |
| + weak_factory_.GetWeakPtr(), context->MakeReplyMessageContext(), |
| + id)); |
| +} |
| + |
| +int32_t PepperVpnProviderMessageFilter::DoBind(SuccessCallback success, |
| + FailureCallback failure) { |
|
bbudge
2016/06/23 18:10:22
nit: s/success/successCallback or successCb, ditto
adrian.belgun
2016/06/24 13:19:37
Done.
|
| + // Initialize shared memory |
| + if (!send_packet_buffer_.get()) { |
| + std::unique_ptr<base::SharedMemory> send_buffer(new base::SharedMemory); |
| + if (!send_buffer.get() || !send_buffer->CreateAndMapAnonymous(kBufferSize)) |
| + return PP_ERROR_NOMEMORY; |
| + |
| + send_packet_buffer_ = base::WrapUnique(new ppapi::VpnProviderSharedBuffer( |
| + kMaxQueuedPackets, kMaxPacketSizeInBytes, std::move(send_buffer))); |
| + if (!send_packet_buffer_.get()) |
| + return PP_ERROR_NOMEMORY; |
| + } |
| + |
| + if (!receive_packet_buffer_.get()) { |
| + std::unique_ptr<base::SharedMemory> send_buffer(new base::SharedMemory); |
|
bbudge
2016/06/23 18:10:22
recv_buffer?
adrian.belgun
2016/06/24 13:19:37
Done.
|
| + if (!send_buffer.get() || !send_buffer->CreateAndMapAnonymous(kBufferSize)) |
| + return PP_ERROR_NOMEMORY; |
| + |
| + receive_packet_buffer_ = |
| + base::WrapUnique(new ppapi::VpnProviderSharedBuffer( |
| + kMaxQueuedPackets, kMaxPacketSizeInBytes, std::move(send_buffer))); |
| + if (!receive_packet_buffer_.get()) |
| + return PP_ERROR_NOMEMORY; |
| + } |
| + |
| + vpn_service_proxy_->Bind( |
| + extension_id_.host(), configuration_id_, configuration_name_, success, |
| + failure, base::WrapUnique(new PepperVpnProviderResourceHostProxyImpl( |
| + weak_factory_.GetWeakPtr()))); |
| + |
| + return PP_OK_COMPLETIONPENDING; |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::OnBindSuccess( |
| + const ppapi::host::ReplyMessageContext& context) { |
| + bound_ = true; |
| + OnBindReply(context, PP_OK); |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::OnBindFailure( |
| + const ppapi::host::ReplyMessageContext& context, |
| + const std::string& error_name, |
| + const std::string& error_message) { |
| + LOG(ERROR) << "PepperVpnProviderMessageFilter::OnBindFailure(): " |
| + << "error_name: " |
| + << "\"" << error_name << "\", " |
| + << "error_message: " |
| + << "\"" << error_message << "\""; |
| + OnBindReply(context, PP_ERROR_FAILED); |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::OnBindReply( |
| + const ppapi::host::ReplyMessageContext& context, |
| + int32_t reply) { |
| + context.params.AppendHandle(ppapi::proxy::SerializedHandle( |
| + send_packet_buffer_->GetHandle(), kBufferSize)); |
| + context.params.AppendHandle(ppapi::proxy::SerializedHandle( |
| + receive_packet_buffer_->GetHandle(), kBufferSize)); |
|
bbudge
2016/06/23 18:10:22
For the failure case, should you return the shm ha
adrian.belgun
2016/06/24 13:19:37
Done. Moved this code to OnBindSuccess().
|
| + |
| + SendReply(context, PpapiPluginMsg_VpnProvider_BindReply( |
| + kMaxQueuedPackets, kMaxPacketSizeInBytes, reply)); |
| +} |
| + |
| +int32_t PepperVpnProviderMessageFilter::DoSendPacket( |
| + const std::vector<char>& packet, |
| + SuccessCallback success, |
| + FailureCallback failure) { |
| + vpn_service_proxy_->SendPacket(extension_id_.host(), packet, success, |
| + failure); |
| + return PP_OK_COMPLETIONPENDING; |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::OnSendPacketSuccess( |
| + const ppapi::host::ReplyMessageContext& context, |
| + uint32_t id) { |
| + OnSendPacketReply(context, id); |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::OnSendPacketFailure( |
| + const ppapi::host::ReplyMessageContext& context, |
| + uint32_t id, |
| + const std::string& error_name, |
| + const std::string& error_message) { |
|
bbudge
2016/06/23 18:10:22
It seems undesirable to drop the error information
adrian.belgun
2016/06/24 13:19:37
Acknowledged. Added logs for developers for plugin
|
| + OnSendPacketReply(context, id); |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::OnSendPacketReply( |
| + const ppapi::host::ReplyMessageContext& context, |
| + int32_t reply) { |
| + SendReply(context, PpapiPluginMsg_VpnProvider_SendPacketReply(reply)); |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::SendOnUnbind() { |
| + configuration_name_.clear(); |
| + configuration_id_.clear(); |
| + bound_ = false; |
| + if (resource_host()) { |
| + resource_host()->host()->SendUnsolicitedReply( |
| + resource_host()->pp_resource(), PpapiPluginMsg_VpnProvider_OnUnbind()); |
| + } |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::SendOnPacketReceived( |
| + const std::vector<char>& packet) { |
| + if (packet.size() > kMaxPacketSizeInBytes) |
| + return; |
| + |
| + uint32_t id; |
| + if (receive_packet_buffer_.get() && |
| + receive_packet_buffer_->GetAvailable(&id)) { |
| + receive_packet_buffer_->SetAvailable(id, false); |
| + DoPacketReceived(packet, id); |
| + } else { |
| + received_packets_.push(packet); |
| + } |
| +} |
| + |
| +void PepperVpnProviderMessageFilter::DoPacketReceived( |
| + const std::vector<char>& packet, |
| + uint32_t id) { |
| + const void* packet_pointer = &packet.front(); |
| + uint32_t packet_size = base::checked_cast<uint32_t>(packet.size()); |
| + memcpy(receive_packet_buffer_->GetBuffer(id), packet_pointer, packet_size); |
| + |
| + if (resource_host()) { |
| + resource_host()->host()->SendUnsolicitedReply( |
| + resource_host()->pp_resource(), |
| + PpapiPluginMsg_VpnProvider_OnPacketReceived(packet_size, id)); |
| + } |
| +} |
| + |
| +int32_t PepperVpnProviderMessageFilter::OnPacketReceivedReply( |
|
bbudge
2016/06/23 18:10:22
Usually, methods in the .cc file are in the same o
adrian.belgun
2016/06/24 13:19:37
Done.
|
| + ppapi::host::HostMessageContext* context, |
| + uint32_t id) { |
| + if (!received_packets_.empty()) { |
| + DoPacketReceived(received_packets_.front(), id); |
| + received_packets_.pop(); |
| + } else { |
| + receive_packet_buffer_->SetAvailable(id, true); |
| + } |
| + |
| + return PP_OK; |
| +} |
| + |
| +} // namespace content |