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