This source file includes following definitions.
- DuplicateHandle
- Init
- SendHandleToBroker
- AddPendingConnect
- Disconnect
- OnBrokerChannelConnected
- OnBrokerPermissionResult
- ReportFailureToClients
- ConnectPluginToBroker
#include "content/renderer/pepper/pepper_broker.h"
#include "build/build_config.h"
#include "content/renderer/pepper/pepper_proxy_channel_delegate_impl.h"
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/pepper/ppb_broker_impl.h"
#include "content/renderer/pepper/renderer_restrict_dispatch_group.h"
#include "ipc/ipc_channel_handle.h"
#include "ppapi/proxy/broker_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/platform_file.h"
#if defined(OS_WIN)
#include <windows.h>
#endif
namespace content {
namespace {
base::SyncSocket::Handle DuplicateHandle(base::SyncSocket::Handle handle) {
base::SyncSocket::Handle out_handle = base::kInvalidPlatformFileValue;
#if defined(OS_WIN)
DWORD options = DUPLICATE_SAME_ACCESS;
if (!::DuplicateHandle(::GetCurrentProcess(),
handle,
::GetCurrentProcess(),
&out_handle,
0,
FALSE,
options)) {
out_handle = base::kInvalidPlatformFileValue;
}
#elif defined(OS_POSIX)
out_handle = ::dup(handle);
#else
#error Not implemented.
#endif
return out_handle;
}
}
PepperBrokerDispatcherWrapper::PepperBrokerDispatcherWrapper() {
}
PepperBrokerDispatcherWrapper::~PepperBrokerDispatcherWrapper() {
}
bool PepperBrokerDispatcherWrapper::Init(
base::ProcessId broker_pid,
const IPC::ChannelHandle& channel_handle) {
if (channel_handle.name.empty())
return false;
#if defined(OS_POSIX)
DCHECK_NE(-1, channel_handle.socket.fd);
if (channel_handle.socket.fd == -1)
return false;
#endif
dispatcher_delegate_.reset(new PepperProxyChannelDelegateImpl);
dispatcher_.reset(
new ppapi::proxy::BrokerHostDispatcher());
if (!dispatcher_->InitBrokerWithChannel(dispatcher_delegate_.get(),
broker_pid,
channel_handle,
true)) {
dispatcher_.reset();
dispatcher_delegate_.reset();
return false;
}
dispatcher_->channel()->SetRestrictDispatchChannelGroup(
kRendererRestrictDispatchGroup_Pepper);
return true;
}
int32_t PepperBrokerDispatcherWrapper::SendHandleToBroker(
PP_Instance instance,
base::SyncSocket::Handle handle) {
IPC::PlatformFileForTransit foreign_socket_handle =
dispatcher_->ShareHandleWithRemote(handle, false);
if (foreign_socket_handle == IPC::InvalidPlatformFileForTransit())
return PP_ERROR_FAILED;
int32_t result;
if (!dispatcher_->Send(
new PpapiMsg_ConnectToPlugin(instance, foreign_socket_handle, &result))) {
base::SyncSocket temp_socket(
IPC::PlatformFileForTransitToPlatformFile(foreign_socket_handle));
return PP_ERROR_FAILED;
}
return result;
}
PepperBroker::PepperBroker(PluginModule* plugin_module)
: plugin_module_(plugin_module) {
DCHECK(plugin_module_);
plugin_module_->SetBroker(this);
}
PepperBroker::~PepperBroker() {
ReportFailureToClients(PP_ERROR_ABORTED);
plugin_module_->SetBroker(NULL);
plugin_module_ = NULL;
}
void PepperBroker::AddPendingConnect(PPB_Broker_Impl* client) {
DCHECK(pending_connects_.find(client) == pending_connects_.end())
<< "Connect was already called for this client";
AddRef();
pending_connects_[client].client = client->AsWeakPtr();
}
void PepperBroker::Disconnect(PPB_Broker_Impl* client) {
pending_connects_.erase(client);
Release();
}
void PepperBroker::OnBrokerChannelConnected(
base::ProcessId broker_pid,
const IPC::ChannelHandle& channel_handle) {
scoped_ptr<PepperBrokerDispatcherWrapper> dispatcher(
new PepperBrokerDispatcherWrapper);
if (!dispatcher->Init(broker_pid, channel_handle)) {
ReportFailureToClients(PP_ERROR_FAILED);
return;
}
dispatcher_.reset(dispatcher.release());
for (ClientMap::iterator i = pending_connects_.begin();
i != pending_connects_.end();) {
base::WeakPtr<PPB_Broker_Impl>& weak_ptr = i->second.client;
if (!i->second.is_authorized) {
++i;
continue;
}
if (weak_ptr.get())
ConnectPluginToBroker(weak_ptr.get());
pending_connects_.erase(i++);
}
}
void PepperBroker::OnBrokerPermissionResult(PPB_Broker_Impl* client,
bool result) {
ClientMap::iterator entry = pending_connects_.find(client);
if (entry == pending_connects_.end())
return;
if (!entry->second.client.get()) {
pending_connects_.erase(entry);
return;
}
if (!result) {
client->BrokerConnected(
ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue),
PP_ERROR_NOACCESS);
pending_connects_.erase(entry);
return;
}
if (dispatcher_) {
ConnectPluginToBroker(client);
pending_connects_.erase(entry);
return;
}
DCHECK(!entry->second.is_authorized);
entry->second.is_authorized = true;
}
PepperBroker::PendingConnection::PendingConnection() : is_authorized(false) {
}
PepperBroker::PendingConnection::~PendingConnection() {
}
void PepperBroker::ReportFailureToClients(int error_code) {
DCHECK_NE(PP_OK, error_code);
for (ClientMap::iterator i = pending_connects_.begin();
i != pending_connects_.end(); ++i) {
base::WeakPtr<PPB_Broker_Impl>& weak_ptr = i->second.client;
if (weak_ptr.get()) {
weak_ptr->BrokerConnected(
ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue),
error_code);
}
}
pending_connects_.clear();
}
void PepperBroker::ConnectPluginToBroker(PPB_Broker_Impl* client) {
base::SyncSocket::Handle plugin_handle = base::kInvalidPlatformFileValue;
int32_t result = PP_OK;
scoped_ptr<base::SyncSocket> broker_socket(new base::SyncSocket());
scoped_ptr<base::SyncSocket> plugin_socket(new base::SyncSocket());
if (base::SyncSocket::CreatePair(broker_socket.get(), plugin_socket.get())) {
result = dispatcher_->SendHandleToBroker(client->pp_instance(),
broker_socket->handle());
if (result == PP_OK)
plugin_handle = DuplicateHandle(plugin_socket->handle());
} else {
result = PP_ERROR_FAILED;
}
client->BrokerConnected(ppapi::PlatformFileToInt(plugin_handle), result);
}
}