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 22using ppapi::PlatformFileToInt; 23using ppapi::thunk::PPB_Broker_API; 24using ppapi::TrackedCallback; 25 26namespace content { 27 28// PPB_Broker_Impl ------------------------------------------------------ 29 30PPB_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 39PPB_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 50PPB_Broker_API* PPB_Broker_Impl::AsPPB_Broker_API() { 51 return this; 52} 53 54int32_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 99int32_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 106GURL 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. 113void 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 127bool 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 139void PPB_Broker_Impl::OnPpapiBrokerChannelCreated( 140 base::ProcessId broker_pid, 141 const IPC::ChannelHandle& handle) { 142 broker_->OnBrokerChannelConnected(broker_pid, handle); 143} 144 145void PPB_Broker_Impl::OnPpapiBrokerPermissionResult(bool result) { 146 broker_->OnBrokerPermissionResult(this, result); 147} 148 149} // namespace content 150