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. 4 5#include "content/renderer/pepper/ppb_broker_impl.h" 6 7#include "base/logging.h" 8#include "content/common/view_messages.h" 9#include "content/renderer/pepper/host_globals.h" 10#include "content/renderer/pepper/pepper_broker.h" 11#include "content/renderer/pepper/pepper_plugin_instance_impl.h" 12#include "content/renderer/pepper/plugin_module.h" 13#include "content/renderer/render_thread_impl.h" 14#include "content/renderer/render_view_impl.h" 15#include "ppapi/c/pp_errors.h" 16#include "ppapi/shared_impl/platform_file.h" 17#include "third_party/WebKit/public/web/WebDocument.h" 18#include "third_party/WebKit/public/web/WebElement.h" 19#include "third_party/WebKit/public/web/WebPluginContainer.h" 20 21using ppapi::PlatformFileToInt; 22using ppapi::thunk::PPB_Broker_API; 23using ppapi::TrackedCallback; 24 25namespace content { 26 27// PPB_Broker_Impl ------------------------------------------------------ 28 29PPB_Broker_Impl::PPB_Broker_Impl(PP_Instance instance) 30 : Resource(ppapi::OBJECT_IS_IMPL, instance), 31 broker_(NULL), 32 connect_callback_(), 33 pipe_handle_(PlatformFileToInt(base::SyncSocket::kInvalidHandle)), 34 routing_id_(RenderThreadImpl::current()->GenerateRoutingID()) { 35 ChildThread::current()->GetRouter()->AddRoute(routing_id_, this); 36} 37 38PPB_Broker_Impl::~PPB_Broker_Impl() { 39 if (broker_) { 40 broker_->Disconnect(this); 41 broker_ = NULL; 42 } 43 44 // The plugin owns the handle. 45 pipe_handle_ = PlatformFileToInt(base::SyncSocket::kInvalidHandle); 46 ChildThread::current()->GetRouter()->RemoveRoute(routing_id_); 47} 48 49PPB_Broker_API* PPB_Broker_Impl::AsPPB_Broker_API() { return this; } 50 51int32_t PPB_Broker_Impl::Connect( 52 scoped_refptr<TrackedCallback> connect_callback) { 53 // TODO(ddorwin): Return PP_ERROR_FAILED if plugin is in-process. 54 55 if (broker_) { 56 // May only be called once. 57 return PP_ERROR_FAILED; 58 } 59 60 PepperPluginInstanceImpl* plugin_instance = 61 HostGlobals::Get()->GetInstance(pp_instance()); 62 if (!plugin_instance) 63 return PP_ERROR_FAILED; 64 PluginModule* module = plugin_instance->module(); 65 const base::FilePath& broker_path = module->path(); 66 67 // The callback must be populated now in case we are connected to the broker 68 // and BrokerConnected is called before ConnectToBroker returns. 69 // Because it must be created now, it must be aborted and cleared if 70 // ConnectToBroker fails. 71 connect_callback_ = connect_callback; 72 73 broker_ = module->GetBroker(); 74 if (!broker_) { 75 broker_ = new PepperBroker(module); 76 77 // Have the browser start the broker process for us. 78 RenderThreadImpl::current()->Send( 79 new ViewHostMsg_OpenChannelToPpapiBroker(routing_id_, broker_path)); 80 } 81 82 RenderThreadImpl::current()->Send( 83 new ViewHostMsg_RequestPpapiBrokerPermission( 84 plugin_instance->render_frame()->render_view()->GetRoutingID(), 85 routing_id_, 86 GetDocumentUrl(), 87 broker_path)); 88 89 // Adds a reference, ensuring that the broker is not deleted when 90 // |broker| goes out of scope. 91 broker_->AddPendingConnect(this); 92 93 return PP_OK_COMPLETIONPENDING; 94} 95 96int32_t PPB_Broker_Impl::GetHandle(int32_t* handle) { 97 if (pipe_handle_ == PlatformFileToInt(base::SyncSocket::kInvalidHandle)) 98 return PP_ERROR_FAILED; // Handle not set yet. 99 *handle = pipe_handle_; 100 return PP_OK; 101} 102 103GURL PPB_Broker_Impl::GetDocumentUrl() { 104 PepperPluginInstanceImpl* plugin_instance = 105 HostGlobals::Get()->GetInstance(pp_instance()); 106 return plugin_instance->container()->element().document().url(); 107} 108 109// Transfers ownership of the handle to the plugin. 110void PPB_Broker_Impl::BrokerConnected(int32_t handle, int32_t result) { 111 DCHECK(pipe_handle_ == PlatformFileToInt(base::SyncSocket::kInvalidHandle)); 112 DCHECK(result == PP_OK || 113 handle == PlatformFileToInt(base::SyncSocket::kInvalidHandle)); 114 115 pipe_handle_ = handle; 116 117 // Synchronous calls are not supported. 118 DCHECK(TrackedCallback::IsPending(connect_callback_)); 119 120 connect_callback_->Run(result); 121} 122 123bool PPB_Broker_Impl::OnMessageReceived(const IPC::Message& message) { 124 bool handled = true; 125 IPC_BEGIN_MESSAGE_MAP(PPB_Broker_Impl, message) 126 IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerChannelCreated, 127 OnPpapiBrokerChannelCreated) 128 IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerPermissionResult, 129 OnPpapiBrokerPermissionResult) 130 IPC_MESSAGE_UNHANDLED(handled = false) 131 IPC_END_MESSAGE_MAP() 132 return handled; 133} 134 135void PPB_Broker_Impl::OnPpapiBrokerChannelCreated( 136 base::ProcessId broker_pid, 137 const IPC::ChannelHandle& handle) { 138 broker_->OnBrokerChannelConnected(broker_pid, handle); 139} 140 141void PPB_Broker_Impl::OnPpapiBrokerPermissionResult(bool result) { 142 broker_->OnBrokerPermissionResult(this, result); 143} 144 145} // namespace content 146