| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/nacl_host/nacl_host_message_filter.h" |
| |
| #include "chrome/browser/extensions/extension_info_map.h" |
| #include "chrome/browser/nacl_host/nacl_browser.h" |
| #include "chrome/browser/nacl_host/nacl_file_host.h" |
| #include "chrome/browser/nacl_host/nacl_process_host.h" |
| #include "chrome/browser/nacl_host/pnacl_host.h" |
| #include "components/nacl/common/nacl_host_messages.h" |
| #include "extensions/common/constants.h" |
| #include "net/url_request/url_request_context.h" |
| #include "net/url_request/url_request_context_getter.h" |
| |
| static base::FilePath GetManifestPath( |
| ExtensionInfoMap* extension_info_map, const std::string& manifest) { |
| GURL manifest_url(manifest); |
| const extensions::Extension* extension = extension_info_map->extensions() |
| .GetExtensionOrAppByURL(manifest_url); |
| if (extension != NULL && |
| manifest_url.SchemeIs(extensions::kExtensionScheme)) { |
| std::string path = manifest_url.path(); |
| TrimString(path, "/", &path); // Remove first slash |
| return extension->path().AppendASCII(path); |
| } |
| return base::FilePath(); |
| } |
| |
| NaClHostMessageFilter::NaClHostMessageFilter( |
| int render_process_id, |
| bool is_off_the_record, |
| const base::FilePath& profile_directory, |
| ExtensionInfoMap* extension_info_map, |
| net::URLRequestContextGetter* request_context) |
| : render_process_id_(render_process_id), |
| off_the_record_(is_off_the_record), |
| profile_directory_(profile_directory), |
| request_context_(request_context), |
| extension_info_map_(extension_info_map), |
| weak_ptr_factory_(this) { |
| } |
| |
| NaClHostMessageFilter::~NaClHostMessageFilter() { |
| } |
| |
| void NaClHostMessageFilter::OnChannelClosing() { |
| PnaclHost::GetInstance()->RendererClosing(render_process_id_); |
| BrowserMessageFilter::OnChannelClosing(); |
| } |
| |
| bool NaClHostMessageFilter::OnMessageReceived(const IPC::Message& message, |
| bool* message_was_ok) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP_EX(NaClHostMessageFilter, message, *message_was_ok) |
| #if !defined(DISABLE_NACL) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClHostMsg_LaunchNaCl, OnLaunchNaCl) |
| IPC_MESSAGE_HANDLER(NaClHostMsg_EnsurePnaclInstalled, |
| OnEnsurePnaclInstalled) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClHostMsg_GetReadonlyPnaclFD, |
| OnGetReadonlyPnaclFd) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClHostMsg_NaClCreateTemporaryFile, |
| OnNaClCreateTemporaryFile) |
| IPC_MESSAGE_HANDLER(NaClHostMsg_NexeTempFileRequest, |
| OnGetNexeFd) |
| IPC_MESSAGE_HANDLER(NaClHostMsg_ReportTranslationFinished, |
| OnTranslationFinished) |
| IPC_MESSAGE_HANDLER(NaClHostMsg_NaClErrorStatus, OnNaClErrorStatus) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClHostMsg_OpenNaClExecutable, |
| OnOpenNaClExecutable) |
| #endif |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| |
| return handled; |
| } |
| |
| net::HostResolver* NaClHostMessageFilter::GetHostResolver() { |
| return request_context_->GetURLRequestContext()->host_resolver(); |
| } |
| |
| #if !defined(DISABLE_NACL) |
| void NaClHostMessageFilter::OnLaunchNaCl( |
| const nacl::NaClLaunchParams& launch_params, |
| IPC::Message* reply_msg) { |
| NaClProcessHost* host = new NaClProcessHost( |
| GURL(launch_params.manifest_url), |
| launch_params.render_view_id, |
| launch_params.permission_bits, |
| launch_params.uses_irt, |
| launch_params.enable_dyncode_syscalls, |
| launch_params.enable_exception_handling, |
| off_the_record_, |
| profile_directory_); |
| base::FilePath manifest_url = |
| GetManifestPath(extension_info_map_.get(), launch_params.manifest_url); |
| host->Launch(this, reply_msg, manifest_url); |
| } |
| |
| void NaClHostMessageFilter::ReplyEnsurePnaclInstalled( |
| int instance, |
| bool success) { |
| Send(new NaClViewMsg_EnsurePnaclInstalledReply(instance, success)); |
| } |
| |
| void NaClHostMessageFilter::SendProgressEnsurePnaclInstalled( |
| int instance, |
| const nacl::PnaclInstallProgress& progress) { |
| // TODO(jvoung): actually send an IPC. |
| } |
| |
| void NaClHostMessageFilter::OnEnsurePnaclInstalled( |
| int instance) { |
| nacl_file_host::EnsurePnaclInstalled( |
| base::Bind(&NaClHostMessageFilter::ReplyEnsurePnaclInstalled, |
| this, instance), |
| base::Bind(&NaClHostMessageFilter::SendProgressEnsurePnaclInstalled, |
| this, instance)); |
| } |
| |
| void NaClHostMessageFilter::OnGetReadonlyPnaclFd( |
| const std::string& filename, IPC::Message* reply_msg) { |
| // This posts a task to another thread, but the renderer will |
| // block until the reply is sent. |
| nacl_file_host::GetReadonlyPnaclFd(this, filename, reply_msg); |
| |
| // This is the first message we receive from the renderer once it knows we |
| // want to use PNaCl, so start the translation cache initialization here. |
| PnaclHost::GetInstance()->Init(); |
| } |
| |
| // Return the temporary file via a reply to the |
| // NaClHostMsg_NaClCreateTemporaryFile sync message. |
| void NaClHostMessageFilter::SyncReturnTemporaryFile( |
| IPC::Message* reply_msg, |
| IPC::PlatformFileForTransit fd) { |
| if (fd == IPC::InvalidPlatformFileForTransit()) { |
| reply_msg->set_reply_error(); |
| } else { |
| NaClHostMsg_NaClCreateTemporaryFile::WriteReplyParams( |
| reply_msg, fd); |
| } |
| Send(reply_msg); |
| } |
| |
| void NaClHostMessageFilter::OnNaClCreateTemporaryFile( |
| IPC::Message* reply_msg) { |
| PnaclHost::GetInstance()->CreateTemporaryFile( |
| PeerHandle(), |
| base::Bind(&NaClHostMessageFilter::SyncReturnTemporaryFile, |
| this, |
| reply_msg)); |
| } |
| |
| // For now, GetNexeFd cache requests always set is_hit to false and returns |
| // a new temporary file via a NaClViewMsg_NexeTempFileReply message. |
| // A future CL will implement the cache lookup logic (and use the currently- |
| // unused parameters) |
| // See also https://code.google.com/p/nativeclient/issues/detail?id=3372 |
| void NaClHostMessageFilter::AsyncReturnTemporaryFile( |
| int pp_instance, |
| IPC::PlatformFileForTransit fd, |
| bool is_hit) { |
| Send(new NaClViewMsg_NexeTempFileReply(pp_instance, is_hit, fd)); |
| } |
| |
| void NaClHostMessageFilter::OnGetNexeFd( |
| int render_view_id, |
| int pp_instance, |
| const nacl::PnaclCacheInfo& cache_info) { |
| if (!cache_info.pexe_url.is_valid()) { |
| LOG(ERROR) << "Bad URL received from GetNexeFd: " << |
| cache_info.pexe_url.possibly_invalid_spec(); |
| BadMessageReceived(); |
| return; |
| } |
| PnaclHost::GetInstance()->GetNexeFd( |
| render_process_id_, |
| PeerHandle(), |
| render_view_id, |
| pp_instance, |
| cache_info, |
| base::Bind(&NaClHostMessageFilter::AsyncReturnTemporaryFile, |
| this, |
| pp_instance)); |
| } |
| |
| void NaClHostMessageFilter::OnTranslationFinished(int instance, bool success) { |
| PnaclHost::GetInstance()->TranslationFinished( |
| render_process_id_, instance, success); |
| } |
| |
| void NaClHostMessageFilter::OnNaClErrorStatus(int render_view_id, |
| int error_id) { |
| NaClBrowser::GetDelegate()->ShowNaClInfobar(render_process_id_, |
| render_view_id, error_id); |
| } |
| |
| void NaClHostMessageFilter::OnOpenNaClExecutable(int render_view_id, |
| const GURL& file_url, |
| IPC::Message* reply_msg) { |
| nacl_file_host::OpenNaClExecutable(this, extension_info_map_, |
| render_view_id, file_url, reply_msg); |
| } |
| #endif |