Index: content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc |
diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc |
index 130245e6022e95266a6e5831463c6f68effa34e5..bd09cccd0abb288f701ec4ebdcd21225d8244475 100644 |
--- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc |
+++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc |
@@ -12,8 +12,176 @@ |
#include "ipc/ipc_message_macros.h" |
#include "ppapi/proxy/ppapi_messages.h" |
+// Probably for moving to other file: |
+#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h" |
+#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h" |
+#include "ppapi/proxy/serialized_structs.h" |
namespace content { |
+InstanceData::InstanceData(PP_Instance instance, |
+ BrowserPpapiHostImpl* host, |
+ IPC::Sender* renderer_sender, |
+ PepperRendererInstanceData renderer_data) |
+ : instance_(instance), |
+ host_(host), |
+ renderer_sender_(renderer_sender), |
+ finished_creators_(0), |
+ renderer_data_(renderer_data), |
+ weak_ptr_factory_(this) { |
+} |
+ |
+InstanceData::InstanceData(const InstanceData& other) |
+ : instance_(other.instance_), |
+ host_(other.host_), |
+ renderer_sender_(other.renderer_sender_), |
+ finished_creators_(other.finished_creators_), |
+ renderer_data_(other.renderer_data_), |
+ weak_ptr_factory_(this) { |
+} |
+ |
+InstanceData::~InstanceData() { |
+} |
+ |
+void InstanceData::CreateResourceHostsFromHost( |
+ int routing_id, |
+ const ppapi::proxy::ResourceMessageCallParams& params, |
+ const std::vector<IPC::Message>& nested_msgs) { |
+ PendingHostCreator* creator = new PendingHostCreator( |
+ routing_id, params.sequence(), nested_msgs.size()); |
+ DCHECK_EQ(0u, host_creator_map_.count(params.sequence())); |
+ host_creator_map_.add(params.sequence(), make_scoped_ptr(creator)); |
+ for (size_t i = 0; i < nested_msgs.size(); ++i) { |
+ const IPC::Message& nested_msg = nested_msgs[i]; |
+ scoped_ptr<ppapi::host::ResourceHost> resource_host; |
+ if (host_->IsValidInstance(instance_)) { |
+ if (nested_msg.type() == PpapiHostMsg_FileRef_CreateForRawFS::ID) { |
+ // FileRef_CreateForRawFS is only permitted from the renderer. Because |
+ // of this, we handle this message here and not in |
+ // content_browser_pepper_host_factory.cc. |
+ base::FilePath external_path; |
+ if (ppapi::UnpackMessage<PpapiHostMsg_FileRef_CreateForRawFS>( |
+ nested_msg, &external_path)) { |
+ resource_host.reset(new PepperFileRefHost( |
+ host_, instance_, params.pp_resource(), external_path)); |
+ } |
+ } else if (nested_msg.type() == |
+ PpapiHostMsg_FileSystem_CreateFromRenderer::ID) { |
+ // Similarly, FileSystem_CreateFromRenderer is only permitted from the |
+ // renderer. |
+ std::string root_url; |
+ PP_FileSystemType file_system_type; |
+ if (ppapi::UnpackMessage<PpapiHostMsg_FileSystem_CreateFromRenderer>( |
+ nested_msg, &root_url, &file_system_type)) { |
+ PepperFileSystemBrowserHost* browser_host = |
+ new PepperFileSystemBrowserHost( |
+ host_, instance_, params.pp_resource(), file_system_type); |
+ resource_host.reset(browser_host); |
+ // Open the file system resource host. This is an asynchronous |
+ // operation, and we must only add the pending resource host and |
+ // send the message once it completes. |
+ browser_host->OpenExisting( |
+ GURL(root_url), |
+ base::Bind(&InstanceData::AddPendingResourceHost, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ creator, |
+ params.sequence(), |
+ i, |
+ base::Passed(&resource_host))); |
+ // Do not fall through; the fall-through case adds the pending |
+ // resource host to the list. We must do this asynchronously. |
+ continue; |
+ } |
+ } |
+ } |
+ |
+ if (!resource_host) { |
+ resource_host = host_->GetPpapiHost()->CreateResourceHost( |
+ params, instance_, nested_msg); |
+ } |
+ |
+ if (resource_host.get()) { |
+ AddPendingResourceHost( |
+ creator, params.sequence(), i, resource_host.Pass()); |
+ } |
+ } |
+ |
+ if (creator->finished()) { |
+ ++finished_creators_; |
+ SendCompletedResourceHosts(*creator); |
+ SendSyncReplyIfNecessary(); |
+ } |
+} |
+ |
+void InstanceData::GetAllPendingResourceHosts( |
+ scoped_ptr<IPC::Message> reply_msg) { |
+ reply_for_sync_request_ = reply_msg.Pass(); |
+ SendSyncReplyIfNecessary(); |
+} |
+ |
+void InstanceData::RendererDidReceiveHosts(int sequence) { |
+ HostCreatorMap::iterator iter = host_creator_map_.find(sequence); |
+ DCHECK(iter != host_creator_map_.end()); |
+ DCHECK(iter->second->finished()); |
+ host_creator_map_.erase(iter); |
+ DCHECK_GT(finished_creators_, 0u); |
+ --finished_creators_; |
+} |
+ |
+void InstanceData::SendCompletedResourceHosts( |
+ const PendingHostCreator& creator) { |
+ // If we're building up a reply to a sync message, we don't need to send an |
+ // async completion message. Just wait until we can send the reply for all |
+ // pending creation requests. |
+ if (!reply_for_sync_request_) { |
+ renderer_sender_->Send(new PpapiHostMsg_CreateResourceHostsFromHostReply( |
+ creator.routing_id(), |
+ ppapi::proxy::CompletedBrowserResourceHosts(creator.sequence_id(), |
+ creator.host_ids()))); |
+ } |
+} |
+ |
+void InstanceData::SendSyncReplyIfNecessary() { |
+ if (host_creator_map_.size() == finished_creators_ && |
+ reply_for_sync_request_) { |
+ // We're servicing a synchronous request for host creation, and we just |
+ // finished the last asynchronous conversion. Now we can package up the |
+ // message and send it. |
+ std::vector<ppapi::proxy::CompletedBrowserResourceHosts> completed_hosts; |
+ for (auto& creator_pair : host_creator_map_) { |
+ completed_hosts.push_back(ppapi::proxy::CompletedBrowserResourceHosts()); |
+ completed_hosts.back().sequence_id = creator_pair.second->sequence_id(); |
+ // We're going to clear host_creator_map_ anyway, so take the vector |
+ // destructively to avoid a copy. |
+ creator_pair.second->TakePendingResourceHostIdsAndReset( |
+ &completed_hosts.back().host_ids); |
+ } |
+ PpapiHostMsg_GetAllPendingResourceHosts::WriteReplyParams( |
+ reply_for_sync_request_.get(), |
+ completed_hosts); |
+ renderer_sender_->Send(reply_for_sync_request_.release()); |
+ // We don't need to wait for an Ack for these; the renderer is blocked and |
+ // will get these created hosts before it can make any more synchronous |
+ // requests to us. |
+ host_creator_map_.clear(); |
+ finished_creators_ = 0; |
+ } |
+} |
+ |
+void InstanceData::AddPendingResourceHost( |
+ PendingHostCreator* creator, |
+ int sequence, |
+ size_t index, |
+ scoped_ptr<ppapi::host::ResourceHost> host) { |
+ int resource_host_id = |
+ host_->GetPpapiHost()->AddPendingResourceHost(host.Pass()); |
+ creator->AddPendingResourceHost(index, resource_host_id); |
+ if (creator->finished()) { |
+ ++finished_creators_; |
+ SendCompletedResourceHosts(*creator); |
+ SendSyncReplyIfNecessary(); |
+ } |
+} |
+ |
// static |
BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess( |
IPC::Sender* sender, |
@@ -85,7 +253,7 @@ base::ProcessHandle BrowserPpapiHostImpl::GetPluginProcessHandle() const { |
} |
bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance) const { |
- return instance_map_.find(instance) != instance_map_.end(); |
+ return (instance_map_.find(instance) != instance_map_.end()); |
} |
bool BrowserPpapiHostImpl::GetRenderFrameIDsForInstance( |
@@ -99,8 +267,8 @@ bool BrowserPpapiHostImpl::GetRenderFrameIDsForInstance( |
return false; |
} |
- *render_process_id = found->second.render_process_id; |
- *render_frame_id = found->second.render_frame_id; |
+ *render_process_id = found->second.renderer_data().render_process_id; |
+ *render_frame_id = found->second.renderer_data().render_frame_id; |
return true; |
} |
@@ -120,14 +288,14 @@ GURL BrowserPpapiHostImpl::GetDocumentURLForInstance(PP_Instance instance) { |
InstanceMap::const_iterator found = instance_map_.find(instance); |
if (found == instance_map_.end()) |
return GURL(); |
- return found->second.document_url; |
+ return found->second.renderer_data().document_url; |
} |
GURL BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance) { |
InstanceMap::const_iterator found = instance_map_.find(instance); |
if (found == instance_map_.end()) |
return GURL(); |
- return found->second.plugin_url; |
+ return found->second.renderer_data().plugin_url; |
} |
void BrowserPpapiHostImpl::SetOnKeepaliveCallback( |
@@ -137,9 +305,12 @@ void BrowserPpapiHostImpl::SetOnKeepaliveCallback( |
void BrowserPpapiHostImpl::AddInstance( |
PP_Instance instance, |
- const PepperRendererInstanceData& instance_data) { |
+ const PepperRendererInstanceData& instance_data, |
+ IPC::Sender* renderer_sender) { |
DCHECK(instance_map_.find(instance) == instance_map_.end()); |
- instance_map_[instance] = instance_data; |
+ instance_map_.insert(InstanceMap::value_type( |
+ instance, |
+ InstanceData(instance, this, renderer_sender, instance_data))); |
} |
void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) { |
@@ -151,11 +322,67 @@ void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) { |
instance_map_.erase(found); |
} |
+PendingHostCreator::PendingHostCreator(int routing_id, |
+ int sequence_id, |
+ size_t nested_msgs_size) |
+ : routing_id_(routing_id), |
+ sequence_id_(sequence_id), |
+ host_ids_(nested_msgs_size, 0), |
+ completed_so_far_(0) { |
+} |
+ |
+PendingHostCreator::~PendingHostCreator() { |
+} |
+ |
+void PendingHostCreator::AddPendingResourceHost(size_t index, int host_id) { |
+ DCHECK(!finished()); |
+ host_ids_[index] = host_id; |
+ ++completed_so_far_; |
+} |
+ |
+void PendingHostCreator::TakePendingResourceHostIdsAndReset( |
+ std::vector<int>* host_ids) { |
+ DCHECK(finished()); |
+ host_ids->swap(host_ids_); |
+ completed_so_far_ = 0; |
+} |
+ |
+void BrowserPpapiHostImpl::CreateResourceHostsFromHost( |
+ int routing_id, |
+ const ppapi::proxy::ResourceMessageCallParams& params, |
+ PP_Instance instance, |
+ const std::vector<IPC::Message>& nested_msgs) { |
+ InstanceMap::iterator iter = instance_map_.find(instance); |
+ if (iter == instance_map_.end()) |
+ return; |
+ iter->second.CreateResourceHostsFromHost( |
+ routing_id, params, nested_msgs); |
+} |
+ |
+bool BrowserPpapiHostImpl::GetAllPendingResourceHosts( |
+ PP_Instance instance, |
+ scoped_ptr<IPC::Message> reply_message) { |
+ InstanceMap::iterator iter = instance_map_.find(instance); |
+ if (iter == instance_map_.end()) |
+ return false; |
+ iter->second.GetAllPendingResourceHosts(reply_message.Pass()); |
+ return true; |
+} |
+ |
+void BrowserPpapiHostImpl::RendererDidReceiveHosts(PP_Instance instance, |
+ int sequence_num) { |
+ InstanceMap::iterator iter = instance_map_.find(instance); |
+ if (iter == instance_map_.end()) |
+ return; |
+ iter->second.RendererDidReceiveHosts(sequence_num); |
+} |
+ |
BrowserPpapiHostImpl::HostMessageFilter::HostMessageFilter( |
ppapi::host::PpapiHost* ppapi_host, |
BrowserPpapiHostImpl* browser_ppapi_host_impl) |
: ppapi_host_(ppapi_host), |
- browser_ppapi_host_impl_(browser_ppapi_host_impl) {} |
+ browser_ppapi_host_impl_(browser_ppapi_host_impl) { |
+} |
bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived( |
const IPC::Message& msg) { |
@@ -209,9 +436,10 @@ void BrowserPpapiHostImpl::OnKeepalive() { |
InstanceMap::iterator instance = instance_map_.begin(); |
int i = 0; |
while (instance != instance_map_.end()) { |
- instance_data[i].render_process_id = instance->second.render_process_id; |
- instance_data[i].render_frame_id = instance->second.render_frame_id; |
- instance_data[i].document_url = instance->second.document_url; |
+ const PepperRendererInstanceData& data = instance->second.renderer_data(); |
+ instance_data[i].render_process_id = data.render_process_id; |
+ instance_data[i].render_frame_id = data.render_frame_id; |
+ instance_data[i].document_url = data.document_url; |
++instance; |
++i; |
} |