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 21 using ppapi::PlatformFileToInt; 22 using ppapi::thunk::PPB_Broker_API; 23 using ppapi::TrackedCallback; 24 25 namespace content { 26 27 // PPB_Broker_Impl ------------------------------------------------------ 28 29 PPB_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 38 PPB_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 49 PPB_Broker_API* PPB_Broker_Impl::AsPPB_Broker_API() { return this; } 50 51 int32_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 96 int32_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 103 GURL 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. 110 void 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 123 bool 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 135 void PPB_Broker_Impl::OnPpapiBrokerChannelCreated( 136 base::ProcessId broker_pid, 137 const IPC::ChannelHandle& handle) { 138 broker_->OnBrokerChannelConnected(broker_pid, handle); 139 } 140 141 void PPB_Broker_Impl::OnPpapiBrokerPermissionResult(bool result) { 142 broker_->OnBrokerPermissionResult(this, result); 143 } 144 145 } // namespace content 146