1 // Copyright 2013 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/browser/renderer_host/pepper/pepper_renderer_connection.h" 6 7 #include "content/browser/browser_child_process_host_impl.h" 8 #include "content/browser/ppapi_plugin_process_host.h" 9 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" 10 #include "content/common/pepper_renderer_instance_data.h" 11 #include "content/common/view_messages.h" 12 #include "content/browser/renderer_host/pepper/pepper_file_ref_host.h" 13 #include "content/public/browser/content_browser_client.h" 14 #include "content/public/common/content_client.h" 15 #include "ipc/ipc_message_macros.h" 16 #include "ppapi/host/resource_host.h" 17 #include "ppapi/proxy/ppapi_message_utils.h" 18 #include "ppapi/proxy/ppapi_messages.h" 19 #include "ppapi/proxy/resource_message_params.h" 20 21 namespace content { 22 23 PepperRendererConnection::PepperRendererConnection(int render_process_id) 24 : render_process_id_(render_process_id) { 25 // Only give the renderer permission for stable APIs. 26 in_process_host_.reset(new BrowserPpapiHostImpl(this, 27 ppapi::PpapiPermissions(), 28 "", 29 base::FilePath(), 30 base::FilePath(), 31 false, 32 NULL)); 33 } 34 35 PepperRendererConnection::~PepperRendererConnection() { 36 } 37 38 BrowserPpapiHostImpl* PepperRendererConnection::GetHostForChildProcess( 39 int child_process_id) const { 40 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 41 42 // Find the plugin which this message refers to. Check NaCl plugins first. 43 BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>( 44 GetContentClient()->browser()->GetExternalBrowserPpapiHost( 45 child_process_id)); 46 47 if (!host) { 48 // Check trusted pepper plugins. 49 for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) { 50 if (iter->process() && 51 iter->process()->GetData().id == child_process_id) { 52 // Found the plugin. 53 host = iter->host_impl(); 54 break; 55 } 56 } 57 } 58 59 // If the message is being sent from an in-process plugin, we own the 60 // BrowserPpapiHost. 61 if (!host && child_process_id == 0) { 62 host = in_process_host_.get(); 63 } 64 65 return host; 66 } 67 68 bool PepperRendererConnection::OnMessageReceived(const IPC::Message& msg, 69 bool* message_was_ok) { 70 if (in_process_host_->GetPpapiHost()->OnMessageReceived(msg)) 71 return true; 72 73 bool handled = true; 74 IPC_BEGIN_MESSAGE_MAP_EX(PepperRendererConnection, msg, *message_was_ok) 75 IPC_MESSAGE_HANDLER(PpapiHostMsg_CreateResourceHostFromHost, 76 OnMsgCreateResourceHostFromHost) 77 IPC_MESSAGE_HANDLER(PpapiHostMsg_FileRef_GetInfoForRenderer, 78 OnMsgFileRefGetInfoForRenderer) 79 IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateInProcessInstance, 80 OnMsgDidCreateInProcessInstance) 81 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteInProcessInstance, 82 OnMsgDidDeleteInProcessInstance) 83 IPC_MESSAGE_UNHANDLED(handled = false) 84 IPC_END_MESSAGE_MAP_EX() 85 86 return handled; 87 } 88 89 void PepperRendererConnection::OnMsgCreateResourceHostFromHost( 90 int routing_id, 91 int child_process_id, 92 const ppapi::proxy::ResourceMessageCallParams& params, 93 PP_Instance instance, 94 const IPC::Message& nested_msg) { 95 BrowserPpapiHostImpl* host = GetHostForChildProcess(child_process_id); 96 97 int pending_resource_host_id; 98 if (!host) { 99 DLOG(ERROR) << "Invalid plugin process ID."; 100 pending_resource_host_id = 0; 101 } else { 102 // FileRef_CreateExternal is only permitted from the renderer. Because of 103 // this, we handle this message here and not in 104 // content_browser_pepper_host_factory.cc. 105 scoped_ptr<ppapi::host::ResourceHost> resource_host; 106 if (host->IsValidInstance(instance)) { 107 if (nested_msg.type() == PpapiHostMsg_FileRef_CreateExternal::ID) { 108 base::FilePath external_path; 109 if (ppapi::UnpackMessage<PpapiHostMsg_FileRef_CreateExternal>( 110 nested_msg, &external_path)) { 111 resource_host.reset(new PepperFileRefHost( 112 host, instance, params.pp_resource(), external_path)); 113 } 114 } 115 } 116 117 if (!resource_host.get()) { 118 resource_host = host->GetPpapiHost()->CreateResourceHost(params, 119 instance, 120 nested_msg); 121 } 122 pending_resource_host_id = 123 host->GetPpapiHost()->AddPendingResourceHost(resource_host.Pass()); 124 } 125 126 Send(new PpapiHostMsg_CreateResourceHostFromHostReply( 127 routing_id, params.sequence(), pending_resource_host_id)); 128 } 129 130 void PepperRendererConnection::OnMsgFileRefGetInfoForRenderer( 131 int routing_id, 132 int child_process_id, 133 int32_t sequence, 134 const std::vector<PP_Resource>& resources) { 135 std::vector<PP_Resource> out_resources; 136 std::vector<PP_FileSystemType> fs_types; 137 std::vector<std::string> file_system_url_specs; 138 std::vector<base::FilePath> external_paths; 139 140 BrowserPpapiHostImpl* host = GetHostForChildProcess(child_process_id); 141 if (host) { 142 for (size_t i = 0; i < resources.size(); ++i) { 143 ppapi::host::ResourceHost* resource_host = 144 host->GetPpapiHost()->GetResourceHost(resources[i]); 145 if (resource_host && resource_host->IsFileRefHost()) { 146 PepperFileRefHost* file_ref_host = 147 static_cast<PepperFileRefHost*>(resource_host); 148 out_resources.push_back(resources[i]); 149 fs_types.push_back(file_ref_host->GetFileSystemType()); 150 file_system_url_specs.push_back(file_ref_host->GetFileSystemURLSpec()); 151 external_paths.push_back(file_ref_host->GetExternalPath()); 152 } 153 } 154 } 155 Send(new PpapiHostMsg_FileRef_GetInfoForRendererReply( 156 routing_id, 157 sequence, 158 out_resources, 159 fs_types, 160 file_system_url_specs, 161 external_paths)); 162 } 163 164 void PepperRendererConnection::OnMsgDidCreateInProcessInstance( 165 PP_Instance instance, 166 const PepperRendererInstanceData& instance_data) { 167 PepperRendererInstanceData data = instance_data; 168 data.render_process_id = render_process_id_; 169 in_process_host_->AddInstance(instance, data); 170 } 171 172 void PepperRendererConnection::OnMsgDidDeleteInProcessInstance( 173 PP_Instance instance) { 174 in_process_host_->DeleteInstance(instance); 175 } 176 177 } // namespace content 178