OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" | 5 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" |
6 | 6 |
7 #include "base/metrics/sparse_histogram.h" | 7 #include "base/metrics/sparse_histogram.h" |
8 #include "content/browser/renderer_host/pepper/pepper_message_filter.h" | 8 #include "content/browser/renderer_host/pepper/pepper_message_filter.h" |
9 #include "content/browser/tracing/trace_message_filter.h" | 9 #include "content/browser/tracing/trace_message_filter.h" |
10 #include "content/common/pepper_renderer_instance_data.h" | 10 #include "content/common/pepper_renderer_instance_data.h" |
11 #include "content/public/common/process_type.h" | 11 #include "content/public/common/process_type.h" |
12 #include "ipc/ipc_message_macros.h" | 12 #include "ipc/ipc_message_macros.h" |
13 #include "ppapi/proxy/ppapi_messages.h" | 13 #include "ppapi/proxy/ppapi_messages.h" |
14 | 14 |
| 15 // Probably for moving to other file: |
| 16 #include "content/browser/renderer_host/pepper/pepper_file_ref_host.h" |
| 17 #include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
" |
| 18 #include "ppapi/proxy/serialized_structs.h" |
15 namespace content { | 19 namespace content { |
16 | 20 |
| 21 InstanceData::InstanceData(PP_Instance instance, |
| 22 BrowserPpapiHostImpl* host, |
| 23 IPC::Sender* renderer_sender, |
| 24 PepperRendererInstanceData renderer_data) |
| 25 : instance_(instance), |
| 26 host_(host), |
| 27 renderer_sender_(renderer_sender), |
| 28 finished_creators_(0), |
| 29 renderer_data_(renderer_data), |
| 30 weak_ptr_factory_(this) { |
| 31 } |
| 32 |
| 33 InstanceData::InstanceData(const InstanceData& other) |
| 34 : instance_(other.instance_), |
| 35 host_(other.host_), |
| 36 renderer_sender_(other.renderer_sender_), |
| 37 finished_creators_(other.finished_creators_), |
| 38 renderer_data_(other.renderer_data_), |
| 39 weak_ptr_factory_(this) { |
| 40 } |
| 41 |
| 42 InstanceData::~InstanceData() { |
| 43 } |
| 44 |
| 45 void InstanceData::CreateResourceHostsFromHost( |
| 46 int routing_id, |
| 47 const ppapi::proxy::ResourceMessageCallParams& params, |
| 48 const std::vector<IPC::Message>& nested_msgs) { |
| 49 PendingHostCreator* creator = new PendingHostCreator( |
| 50 routing_id, params.sequence(), nested_msgs.size()); |
| 51 DCHECK_EQ(0u, host_creator_map_.count(params.sequence())); |
| 52 host_creator_map_.add(params.sequence(), make_scoped_ptr(creator)); |
| 53 for (size_t i = 0; i < nested_msgs.size(); ++i) { |
| 54 const IPC::Message& nested_msg = nested_msgs[i]; |
| 55 scoped_ptr<ppapi::host::ResourceHost> resource_host; |
| 56 if (host_->IsValidInstance(instance_)) { |
| 57 if (nested_msg.type() == PpapiHostMsg_FileRef_CreateForRawFS::ID) { |
| 58 // FileRef_CreateForRawFS is only permitted from the renderer. Because |
| 59 // of this, we handle this message here and not in |
| 60 // content_browser_pepper_host_factory.cc. |
| 61 base::FilePath external_path; |
| 62 if (ppapi::UnpackMessage<PpapiHostMsg_FileRef_CreateForRawFS>( |
| 63 nested_msg, &external_path)) { |
| 64 resource_host.reset(new PepperFileRefHost( |
| 65 host_, instance_, params.pp_resource(), external_path)); |
| 66 } |
| 67 } else if (nested_msg.type() == |
| 68 PpapiHostMsg_FileSystem_CreateFromRenderer::ID) { |
| 69 // Similarly, FileSystem_CreateFromRenderer is only permitted from the |
| 70 // renderer. |
| 71 std::string root_url; |
| 72 PP_FileSystemType file_system_type; |
| 73 if (ppapi::UnpackMessage<PpapiHostMsg_FileSystem_CreateFromRenderer>( |
| 74 nested_msg, &root_url, &file_system_type)) { |
| 75 PepperFileSystemBrowserHost* browser_host = |
| 76 new PepperFileSystemBrowserHost( |
| 77 host_, instance_, params.pp_resource(), file_system_type); |
| 78 resource_host.reset(browser_host); |
| 79 // Open the file system resource host. This is an asynchronous |
| 80 // operation, and we must only add the pending resource host and |
| 81 // send the message once it completes. |
| 82 browser_host->OpenExisting( |
| 83 GURL(root_url), |
| 84 base::Bind(&InstanceData::AddPendingResourceHost, |
| 85 weak_ptr_factory_.GetWeakPtr(), |
| 86 creator, |
| 87 params.sequence(), |
| 88 i, |
| 89 base::Passed(&resource_host))); |
| 90 // Do not fall through; the fall-through case adds the pending |
| 91 // resource host to the list. We must do this asynchronously. |
| 92 continue; |
| 93 } |
| 94 } |
| 95 } |
| 96 |
| 97 if (!resource_host) { |
| 98 resource_host = host_->GetPpapiHost()->CreateResourceHost( |
| 99 params, instance_, nested_msg); |
| 100 } |
| 101 |
| 102 if (resource_host.get()) { |
| 103 AddPendingResourceHost( |
| 104 creator, params.sequence(), i, resource_host.Pass()); |
| 105 } |
| 106 } |
| 107 |
| 108 if (creator->finished()) { |
| 109 ++finished_creators_; |
| 110 SendCompletedResourceHosts(*creator); |
| 111 SendSyncReplyIfNecessary(); |
| 112 } |
| 113 } |
| 114 |
| 115 void InstanceData::GetAllPendingResourceHosts( |
| 116 scoped_ptr<IPC::Message> reply_msg) { |
| 117 reply_for_sync_request_ = reply_msg.Pass(); |
| 118 SendSyncReplyIfNecessary(); |
| 119 } |
| 120 |
| 121 void InstanceData::RendererDidReceiveHosts(int sequence) { |
| 122 HostCreatorMap::iterator iter = host_creator_map_.find(sequence); |
| 123 DCHECK(iter != host_creator_map_.end()); |
| 124 DCHECK(iter->second->finished()); |
| 125 host_creator_map_.erase(iter); |
| 126 DCHECK_GT(finished_creators_, 0u); |
| 127 --finished_creators_; |
| 128 } |
| 129 |
| 130 void InstanceData::SendCompletedResourceHosts( |
| 131 const PendingHostCreator& creator) { |
| 132 // If we're building up a reply to a sync message, we don't need to send an |
| 133 // async completion message. Just wait until we can send the reply for all |
| 134 // pending creation requests. |
| 135 if (!reply_for_sync_request_) { |
| 136 renderer_sender_->Send(new PpapiHostMsg_CreateResourceHostsFromHostReply( |
| 137 creator.routing_id(), |
| 138 ppapi::proxy::CompletedBrowserResourceHosts(creator.sequence_id(), |
| 139 creator.host_ids()))); |
| 140 } |
| 141 } |
| 142 |
| 143 void InstanceData::SendSyncReplyIfNecessary() { |
| 144 if (host_creator_map_.size() == finished_creators_ && |
| 145 reply_for_sync_request_) { |
| 146 // We're servicing a synchronous request for host creation, and we just |
| 147 // finished the last asynchronous conversion. Now we can package up the |
| 148 // message and send it. |
| 149 std::vector<ppapi::proxy::CompletedBrowserResourceHosts> completed_hosts; |
| 150 for (auto& creator_pair : host_creator_map_) { |
| 151 completed_hosts.push_back(ppapi::proxy::CompletedBrowserResourceHosts()); |
| 152 completed_hosts.back().sequence_id = creator_pair.second->sequence_id(); |
| 153 // We're going to clear host_creator_map_ anyway, so take the vector |
| 154 // destructively to avoid a copy. |
| 155 creator_pair.second->TakePendingResourceHostIdsAndReset( |
| 156 &completed_hosts.back().host_ids); |
| 157 } |
| 158 PpapiHostMsg_GetAllPendingResourceHosts::WriteReplyParams( |
| 159 reply_for_sync_request_.get(), |
| 160 completed_hosts); |
| 161 renderer_sender_->Send(reply_for_sync_request_.release()); |
| 162 // We don't need to wait for an Ack for these; the renderer is blocked and |
| 163 // will get these created hosts before it can make any more synchronous |
| 164 // requests to us. |
| 165 host_creator_map_.clear(); |
| 166 finished_creators_ = 0; |
| 167 } |
| 168 } |
| 169 |
| 170 void InstanceData::AddPendingResourceHost( |
| 171 PendingHostCreator* creator, |
| 172 int sequence, |
| 173 size_t index, |
| 174 scoped_ptr<ppapi::host::ResourceHost> host) { |
| 175 int resource_host_id = |
| 176 host_->GetPpapiHost()->AddPendingResourceHost(host.Pass()); |
| 177 creator->AddPendingResourceHost(index, resource_host_id); |
| 178 if (creator->finished()) { |
| 179 ++finished_creators_; |
| 180 SendCompletedResourceHosts(*creator); |
| 181 SendSyncReplyIfNecessary(); |
| 182 } |
| 183 } |
| 184 |
17 // static | 185 // static |
18 BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess( | 186 BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess( |
19 IPC::Sender* sender, | 187 IPC::Sender* sender, |
20 ppapi::PpapiPermissions permissions, | 188 ppapi::PpapiPermissions permissions, |
21 base::ProcessHandle plugin_child_process, | 189 base::ProcessHandle plugin_child_process, |
22 IPC::ChannelProxy* channel, | 190 IPC::ChannelProxy* channel, |
23 int render_process_id, | 191 int render_process_id, |
24 int render_view_id, | 192 int render_view_id, |
25 const base::FilePath& profile_directory) { | 193 const base::FilePath& profile_directory) { |
26 // The plugin name and path shouldn't be needed for external plugins. | 194 // The plugin name and path shouldn't be needed for external plugins. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 return ppapi_host_.get(); | 246 return ppapi_host_.get(); |
79 } | 247 } |
80 | 248 |
81 base::ProcessHandle BrowserPpapiHostImpl::GetPluginProcessHandle() const { | 249 base::ProcessHandle BrowserPpapiHostImpl::GetPluginProcessHandle() const { |
82 // Handle should previously have been set before use. | 250 // Handle should previously have been set before use. |
83 DCHECK(in_process_ || plugin_process_handle_ != base::kNullProcessHandle); | 251 DCHECK(in_process_ || plugin_process_handle_ != base::kNullProcessHandle); |
84 return plugin_process_handle_; | 252 return plugin_process_handle_; |
85 } | 253 } |
86 | 254 |
87 bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance) const { | 255 bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance) const { |
88 return instance_map_.find(instance) != instance_map_.end(); | 256 return (instance_map_.find(instance) != instance_map_.end()); |
89 } | 257 } |
90 | 258 |
91 bool BrowserPpapiHostImpl::GetRenderFrameIDsForInstance( | 259 bool BrowserPpapiHostImpl::GetRenderFrameIDsForInstance( |
92 PP_Instance instance, | 260 PP_Instance instance, |
93 int* render_process_id, | 261 int* render_process_id, |
94 int* render_frame_id) const { | 262 int* render_frame_id) const { |
95 InstanceMap::const_iterator found = instance_map_.find(instance); | 263 InstanceMap::const_iterator found = instance_map_.find(instance); |
96 if (found == instance_map_.end()) { | 264 if (found == instance_map_.end()) { |
97 *render_process_id = 0; | 265 *render_process_id = 0; |
98 *render_frame_id = 0; | 266 *render_frame_id = 0; |
99 return false; | 267 return false; |
100 } | 268 } |
101 | 269 |
102 *render_process_id = found->second.render_process_id; | 270 *render_process_id = found->second.renderer_data().render_process_id; |
103 *render_frame_id = found->second.render_frame_id; | 271 *render_frame_id = found->second.renderer_data().render_frame_id; |
104 return true; | 272 return true; |
105 } | 273 } |
106 | 274 |
107 const std::string& BrowserPpapiHostImpl::GetPluginName() { | 275 const std::string& BrowserPpapiHostImpl::GetPluginName() { |
108 return plugin_name_; | 276 return plugin_name_; |
109 } | 277 } |
110 | 278 |
111 const base::FilePath& BrowserPpapiHostImpl::GetPluginPath() { | 279 const base::FilePath& BrowserPpapiHostImpl::GetPluginPath() { |
112 return plugin_path_; | 280 return plugin_path_; |
113 } | 281 } |
114 | 282 |
115 const base::FilePath& BrowserPpapiHostImpl::GetProfileDataDirectory() { | 283 const base::FilePath& BrowserPpapiHostImpl::GetProfileDataDirectory() { |
116 return profile_data_directory_; | 284 return profile_data_directory_; |
117 } | 285 } |
118 | 286 |
119 GURL BrowserPpapiHostImpl::GetDocumentURLForInstance(PP_Instance instance) { | 287 GURL BrowserPpapiHostImpl::GetDocumentURLForInstance(PP_Instance instance) { |
120 InstanceMap::const_iterator found = instance_map_.find(instance); | 288 InstanceMap::const_iterator found = instance_map_.find(instance); |
121 if (found == instance_map_.end()) | 289 if (found == instance_map_.end()) |
122 return GURL(); | 290 return GURL(); |
123 return found->second.document_url; | 291 return found->second.renderer_data().document_url; |
124 } | 292 } |
125 | 293 |
126 GURL BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance) { | 294 GURL BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance) { |
127 InstanceMap::const_iterator found = instance_map_.find(instance); | 295 InstanceMap::const_iterator found = instance_map_.find(instance); |
128 if (found == instance_map_.end()) | 296 if (found == instance_map_.end()) |
129 return GURL(); | 297 return GURL(); |
130 return found->second.plugin_url; | 298 return found->second.renderer_data().plugin_url; |
131 } | 299 } |
132 | 300 |
133 void BrowserPpapiHostImpl::SetOnKeepaliveCallback( | 301 void BrowserPpapiHostImpl::SetOnKeepaliveCallback( |
134 const BrowserPpapiHost::OnKeepaliveCallback& callback) { | 302 const BrowserPpapiHost::OnKeepaliveCallback& callback) { |
135 on_keepalive_callback_ = callback; | 303 on_keepalive_callback_ = callback; |
136 } | 304 } |
137 | 305 |
138 void BrowserPpapiHostImpl::AddInstance( | 306 void BrowserPpapiHostImpl::AddInstance( |
139 PP_Instance instance, | 307 PP_Instance instance, |
140 const PepperRendererInstanceData& instance_data) { | 308 const PepperRendererInstanceData& instance_data, |
| 309 IPC::Sender* renderer_sender) { |
141 DCHECK(instance_map_.find(instance) == instance_map_.end()); | 310 DCHECK(instance_map_.find(instance) == instance_map_.end()); |
142 instance_map_[instance] = instance_data; | 311 instance_map_.insert(InstanceMap::value_type( |
| 312 instance, |
| 313 InstanceData(instance, this, renderer_sender, instance_data))); |
143 } | 314 } |
144 | 315 |
145 void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) { | 316 void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) { |
146 InstanceMap::iterator found = instance_map_.find(instance); | 317 InstanceMap::iterator found = instance_map_.find(instance); |
147 if (found == instance_map_.end()) { | 318 if (found == instance_map_.end()) { |
148 NOTREACHED(); | 319 NOTREACHED(); |
149 return; | 320 return; |
150 } | 321 } |
151 instance_map_.erase(found); | 322 instance_map_.erase(found); |
152 } | 323 } |
153 | 324 |
| 325 PendingHostCreator::PendingHostCreator(int routing_id, |
| 326 int sequence_id, |
| 327 size_t nested_msgs_size) |
| 328 : routing_id_(routing_id), |
| 329 sequence_id_(sequence_id), |
| 330 host_ids_(nested_msgs_size, 0), |
| 331 completed_so_far_(0) { |
| 332 } |
| 333 |
| 334 PendingHostCreator::~PendingHostCreator() { |
| 335 } |
| 336 |
| 337 void PendingHostCreator::AddPendingResourceHost(size_t index, int host_id) { |
| 338 DCHECK(!finished()); |
| 339 host_ids_[index] = host_id; |
| 340 ++completed_so_far_; |
| 341 } |
| 342 |
| 343 void PendingHostCreator::TakePendingResourceHostIdsAndReset( |
| 344 std::vector<int>* host_ids) { |
| 345 DCHECK(finished()); |
| 346 host_ids->swap(host_ids_); |
| 347 completed_so_far_ = 0; |
| 348 } |
| 349 |
| 350 void BrowserPpapiHostImpl::CreateResourceHostsFromHost( |
| 351 int routing_id, |
| 352 const ppapi::proxy::ResourceMessageCallParams& params, |
| 353 PP_Instance instance, |
| 354 const std::vector<IPC::Message>& nested_msgs) { |
| 355 InstanceMap::iterator iter = instance_map_.find(instance); |
| 356 if (iter == instance_map_.end()) |
| 357 return; |
| 358 iter->second.CreateResourceHostsFromHost( |
| 359 routing_id, params, nested_msgs); |
| 360 } |
| 361 |
| 362 bool BrowserPpapiHostImpl::GetAllPendingResourceHosts( |
| 363 PP_Instance instance, |
| 364 scoped_ptr<IPC::Message> reply_message) { |
| 365 InstanceMap::iterator iter = instance_map_.find(instance); |
| 366 if (iter == instance_map_.end()) |
| 367 return false; |
| 368 iter->second.GetAllPendingResourceHosts(reply_message.Pass()); |
| 369 return true; |
| 370 } |
| 371 |
| 372 void BrowserPpapiHostImpl::RendererDidReceiveHosts(PP_Instance instance, |
| 373 int sequence_num) { |
| 374 InstanceMap::iterator iter = instance_map_.find(instance); |
| 375 if (iter == instance_map_.end()) |
| 376 return; |
| 377 iter->second.RendererDidReceiveHosts(sequence_num); |
| 378 } |
| 379 |
154 BrowserPpapiHostImpl::HostMessageFilter::HostMessageFilter( | 380 BrowserPpapiHostImpl::HostMessageFilter::HostMessageFilter( |
155 ppapi::host::PpapiHost* ppapi_host, | 381 ppapi::host::PpapiHost* ppapi_host, |
156 BrowserPpapiHostImpl* browser_ppapi_host_impl) | 382 BrowserPpapiHostImpl* browser_ppapi_host_impl) |
157 : ppapi_host_(ppapi_host), | 383 : ppapi_host_(ppapi_host), |
158 browser_ppapi_host_impl_(browser_ppapi_host_impl) {} | 384 browser_ppapi_host_impl_(browser_ppapi_host_impl) { |
| 385 } |
159 | 386 |
160 bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived( | 387 bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived( |
161 const IPC::Message& msg) { | 388 const IPC::Message& msg) { |
162 // Don't forward messages if our owner object has been destroyed. | 389 // Don't forward messages if our owner object has been destroyed. |
163 if (!ppapi_host_) | 390 if (!ppapi_host_) |
164 return false; | 391 return false; |
165 | 392 |
166 bool handled = true; | 393 bool handled = true; |
167 IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl::HostMessageFilter, msg) | 394 IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl::HostMessageFilter, msg) |
168 // Add necessary message handlers here. | 395 // Add necessary message handlers here. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 // for this module together. | 429 // for this module together. |
203 | 430 |
204 if (on_keepalive_callback_.is_null()) | 431 if (on_keepalive_callback_.is_null()) |
205 return; | 432 return; |
206 | 433 |
207 BrowserPpapiHost::OnKeepaliveInstanceData instance_data(instance_map_.size()); | 434 BrowserPpapiHost::OnKeepaliveInstanceData instance_data(instance_map_.size()); |
208 | 435 |
209 InstanceMap::iterator instance = instance_map_.begin(); | 436 InstanceMap::iterator instance = instance_map_.begin(); |
210 int i = 0; | 437 int i = 0; |
211 while (instance != instance_map_.end()) { | 438 while (instance != instance_map_.end()) { |
212 instance_data[i].render_process_id = instance->second.render_process_id; | 439 const PepperRendererInstanceData& data = instance->second.renderer_data(); |
213 instance_data[i].render_frame_id = instance->second.render_frame_id; | 440 instance_data[i].render_process_id = data.render_process_id; |
214 instance_data[i].document_url = instance->second.document_url; | 441 instance_data[i].render_frame_id = data.render_frame_id; |
| 442 instance_data[i].document_url = data.document_url; |
215 ++instance; | 443 ++instance; |
216 ++i; | 444 ++i; |
217 } | 445 } |
218 on_keepalive_callback_.Run(instance_data, profile_data_directory_); | 446 on_keepalive_callback_.Run(instance_data, profile_data_directory_); |
219 } | 447 } |
220 | 448 |
221 } // namespace content | 449 } // namespace content |
OLD | NEW |