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::kInvalidPlatformFileValue)), 35 routing_id_(RenderThreadImpl::current()->GenerateRoutingID()) { 36 ChildThread::current()->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::kInvalidPlatformFileValue); 47 ChildThread::current()->RemoveRoute(routing_id_); 48 } 49 50 PPB_Broker_API* PPB_Broker_Impl::AsPPB_Broker_API() { 51 return this; 52 } 53 54 int32_t PPB_Broker_Impl::Connect( 55 scoped_refptr<TrackedCallback> connect_callback) { 56 // TODO(ddorwin): Return PP_ERROR_FAILED if plugin is in-process. 57 58 if (broker_) { 59 // May only be called once. 60 return PP_ERROR_FAILED; 61 } 62 63 PepperPluginInstanceImpl* plugin_instance = 64 HostGlobals::Get()->GetInstance(pp_instance()); 65 if (!plugin_instance) 66 return PP_ERROR_FAILED; 67 PluginModule* module = plugin_instance->module(); 68 const base::FilePath& broker_path = module->path(); 69 70 // The callback must be populated now in case we are connected to the broker 71 // and BrokerConnected is called before ConnectToBroker returns. 72 // Because it must be created now, it must be aborted and cleared if 73 // ConnectToBroker fails. 74 connect_callback_ = connect_callback; 75 76 broker_ = module->GetBroker(); 77 if (!broker_) { 78 broker_ = new PepperBroker(module); 79 80 // Have the browser start the broker process for us. 81 RenderThreadImpl::current()->Send(new ViewHostMsg_OpenChannelToPpapiBroker( 82 routing_id_, broker_path)); 83 } 84 85 RenderThreadImpl::current()->Send( 86 new ViewHostMsg_RequestPpapiBrokerPermission( 87 plugin_instance->render_frame()->render_view()->GetRoutingID(), 88 routing_id_, 89 GetDocumentUrl(), 90 broker_path)); 91 92 // Adds a reference, ensuring that the broker is not deleted when 93 // |broker| goes out of scope. 94 broker_->AddPendingConnect(this); 95 96 return PP_OK_COMPLETIONPENDING; 97 } 98 99 int32_t PPB_Broker_Impl::GetHandle(int32_t* handle) { 100 if (pipe_handle_ == PlatformFileToInt(base::kInvalidPlatformFileValue)) 101 return PP_ERROR_FAILED; // Handle not set yet. 102 *handle = pipe_handle_; 103 return PP_OK; 104 } 105 106 GURL PPB_Broker_Impl::GetDocumentUrl() { 107 PepperPluginInstanceImpl* plugin_instance = 108 HostGlobals::Get()->GetInstance(pp_instance()); 109 return plugin_instance->container()->element().document().url(); 110 } 111 112 // Transfers ownership of the handle to the plugin. 113 void PPB_Broker_Impl::BrokerConnected(int32_t handle, int32_t result) { 114 DCHECK(pipe_handle_ == 115 PlatformFileToInt(base::kInvalidPlatformFileValue)); 116 DCHECK(result == PP_OK || 117 handle == PlatformFileToInt(base::kInvalidPlatformFileValue)); 118 119 pipe_handle_ = handle; 120 121 // Synchronous calls are not supported. 122 DCHECK(TrackedCallback::IsPending(connect_callback_)); 123 124 connect_callback_->Run(result); 125 } 126 127 bool PPB_Broker_Impl::OnMessageReceived(const IPC::Message& message) { 128 bool handled = true; 129 IPC_BEGIN_MESSAGE_MAP(PPB_Broker_Impl, message) 130 IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerChannelCreated, 131 OnPpapiBrokerChannelCreated) 132 IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerPermissionResult, 133 OnPpapiBrokerPermissionResult) 134 IPC_MESSAGE_UNHANDLED(handled = false) 135 IPC_END_MESSAGE_MAP() 136 return handled; 137 } 138 139 void PPB_Broker_Impl::OnPpapiBrokerChannelCreated( 140 base::ProcessId broker_pid, 141 const IPC::ChannelHandle& handle) { 142 broker_->OnBrokerChannelConnected(broker_pid, handle); 143 } 144 145 void PPB_Broker_Impl::OnPpapiBrokerPermissionResult(bool result) { 146 broker_->OnBrokerPermissionResult(this, result); 147 } 148 149 } // namespace content 150