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 "chrome/browser/nacl_host/nacl_host_message_filter.h" 6 7 #include "chrome/browser/extensions/extension_info_map.h" 8 #include "chrome/browser/nacl_host/nacl_browser.h" 9 #include "chrome/browser/nacl_host/nacl_file_host.h" 10 #include "chrome/browser/nacl_host/nacl_process_host.h" 11 #include "chrome/browser/nacl_host/pnacl_host.h" 12 #include "components/nacl/common/nacl_host_messages.h" 13 #include "extensions/common/constants.h" 14 #include "ipc/ipc_platform_file.h" 15 #include "net/url_request/url_request_context.h" 16 #include "net/url_request/url_request_context_getter.h" 17 18 static base::FilePath GetManifestPath( 19 ExtensionInfoMap* extension_info_map, const std::string& manifest) { 20 GURL manifest_url(manifest); 21 const extensions::Extension* extension = extension_info_map->extensions() 22 .GetExtensionOrAppByURL(manifest_url); 23 if (extension != NULL && 24 manifest_url.SchemeIs(extensions::kExtensionScheme)) { 25 std::string path = manifest_url.path(); 26 TrimString(path, "/", &path); // Remove first slash 27 return extension->path().AppendASCII(path); 28 } 29 return base::FilePath(); 30 } 31 32 NaClHostMessageFilter::NaClHostMessageFilter( 33 int render_process_id, 34 bool is_off_the_record, 35 const base::FilePath& profile_directory, 36 ExtensionInfoMap* extension_info_map, 37 net::URLRequestContextGetter* request_context) 38 : render_process_id_(render_process_id), 39 off_the_record_(is_off_the_record), 40 profile_directory_(profile_directory), 41 request_context_(request_context), 42 extension_info_map_(extension_info_map), 43 weak_ptr_factory_(this) { 44 } 45 46 NaClHostMessageFilter::~NaClHostMessageFilter() { 47 } 48 49 void NaClHostMessageFilter::OnChannelClosing() { 50 PnaclHost::GetInstance()->RendererClosing(render_process_id_); 51 BrowserMessageFilter::OnChannelClosing(); 52 } 53 54 bool NaClHostMessageFilter::OnMessageReceived(const IPC::Message& message, 55 bool* message_was_ok) { 56 bool handled = true; 57 IPC_BEGIN_MESSAGE_MAP_EX(NaClHostMessageFilter, message, *message_was_ok) 58 #if !defined(DISABLE_NACL) 59 IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClHostMsg_LaunchNaCl, OnLaunchNaCl) 60 IPC_MESSAGE_HANDLER(NaClHostMsg_EnsurePnaclInstalled, 61 OnEnsurePnaclInstalled) 62 IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClHostMsg_GetReadonlyPnaclFD, 63 OnGetReadonlyPnaclFd) 64 IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClHostMsg_NaClCreateTemporaryFile, 65 OnNaClCreateTemporaryFile) 66 IPC_MESSAGE_HANDLER(NaClHostMsg_NexeTempFileRequest, 67 OnGetNexeFd) 68 IPC_MESSAGE_HANDLER(NaClHostMsg_ReportTranslationFinished, 69 OnTranslationFinished) 70 IPC_MESSAGE_HANDLER(NaClHostMsg_NaClErrorStatus, OnNaClErrorStatus) 71 IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClHostMsg_OpenNaClExecutable, 72 OnOpenNaClExecutable) 73 #endif 74 IPC_MESSAGE_UNHANDLED(handled = false) 75 IPC_END_MESSAGE_MAP() 76 77 return handled; 78 } 79 80 net::HostResolver* NaClHostMessageFilter::GetHostResolver() { 81 return request_context_->GetURLRequestContext()->host_resolver(); 82 } 83 84 #if !defined(DISABLE_NACL) 85 void NaClHostMessageFilter::OnLaunchNaCl( 86 const nacl::NaClLaunchParams& launch_params, 87 IPC::Message* reply_msg) { 88 NaClProcessHost* host = new NaClProcessHost( 89 GURL(launch_params.manifest_url), 90 launch_params.render_view_id, 91 launch_params.permission_bits, 92 launch_params.uses_irt, 93 launch_params.enable_dyncode_syscalls, 94 launch_params.enable_exception_handling, 95 off_the_record_, 96 profile_directory_); 97 base::FilePath manifest_url = 98 GetManifestPath(extension_info_map_.get(), launch_params.manifest_url); 99 host->Launch(this, reply_msg, manifest_url); 100 } 101 102 void NaClHostMessageFilter::ReplyEnsurePnaclInstalled( 103 int instance, 104 bool success) { 105 Send(new NaClViewMsg_EnsurePnaclInstalledReply(instance, success)); 106 } 107 108 void NaClHostMessageFilter::SendProgressEnsurePnaclInstalled( 109 int instance, 110 const nacl::PnaclInstallProgress& progress) { 111 // TODO(jvoung): actually send an IPC. 112 } 113 114 void NaClHostMessageFilter::OnEnsurePnaclInstalled( 115 int instance) { 116 nacl_file_host::EnsurePnaclInstalled( 117 base::Bind(&NaClHostMessageFilter::ReplyEnsurePnaclInstalled, 118 this, instance), 119 base::Bind(&NaClHostMessageFilter::SendProgressEnsurePnaclInstalled, 120 this, instance)); 121 } 122 123 void NaClHostMessageFilter::OnGetReadonlyPnaclFd( 124 const std::string& filename, IPC::Message* reply_msg) { 125 // This posts a task to another thread, but the renderer will 126 // block until the reply is sent. 127 nacl_file_host::GetReadonlyPnaclFd(this, filename, reply_msg); 128 129 // This is the first message we receive from the renderer once it knows we 130 // want to use PNaCl, so start the translation cache initialization here. 131 PnaclHost::GetInstance()->Init(); 132 } 133 134 // Return the temporary file via a reply to the 135 // NaClHostMsg_NaClCreateTemporaryFile sync message. 136 void NaClHostMessageFilter::SyncReturnTemporaryFile( 137 IPC::Message* reply_msg, 138 base::PlatformFile fd) { 139 if (fd == base::kInvalidPlatformFileValue) { 140 reply_msg->set_reply_error(); 141 } else { 142 NaClHostMsg_NaClCreateTemporaryFile::WriteReplyParams( 143 reply_msg, 144 IPC::GetFileHandleForProcess(fd, PeerHandle(), true)); 145 } 146 Send(reply_msg); 147 } 148 149 void NaClHostMessageFilter::OnNaClCreateTemporaryFile( 150 IPC::Message* reply_msg) { 151 PnaclHost::GetInstance()->CreateTemporaryFile( 152 base::Bind(&NaClHostMessageFilter::SyncReturnTemporaryFile, 153 this, 154 reply_msg)); 155 } 156 157 void NaClHostMessageFilter::AsyncReturnTemporaryFile( 158 int pp_instance, 159 base::PlatformFile fd, 160 bool is_hit) { 161 Send(new NaClViewMsg_NexeTempFileReply( 162 pp_instance, 163 is_hit, 164 // Don't close our copy of the handle, because PnaclHost will use it 165 // when the translation finishes. 166 IPC::GetFileHandleForProcess(fd, PeerHandle(), false))); 167 } 168 169 void NaClHostMessageFilter::OnGetNexeFd( 170 int render_view_id, 171 int pp_instance, 172 const nacl::PnaclCacheInfo& cache_info) { 173 if (!cache_info.pexe_url.is_valid()) { 174 LOG(ERROR) << "Bad URL received from GetNexeFd: " << 175 cache_info.pexe_url.possibly_invalid_spec(); 176 BadMessageReceived(); 177 return; 178 } 179 180 PnaclHost::GetInstance()->GetNexeFd( 181 render_process_id_, 182 render_view_id, 183 pp_instance, 184 off_the_record_, 185 cache_info, 186 base::Bind(&NaClHostMessageFilter::AsyncReturnTemporaryFile, 187 this, 188 pp_instance)); 189 } 190 191 void NaClHostMessageFilter::OnTranslationFinished(int instance, bool success) { 192 PnaclHost::GetInstance()->TranslationFinished( 193 render_process_id_, instance, success); 194 } 195 196 void NaClHostMessageFilter::OnNaClErrorStatus(int render_view_id, 197 int error_id) { 198 NaClBrowser::GetDelegate()->ShowNaClInfobar(render_process_id_, 199 render_view_id, error_id); 200 } 201 202 void NaClHostMessageFilter::OnOpenNaClExecutable(int render_view_id, 203 const GURL& file_url, 204 IPC::Message* reply_msg) { 205 nacl_file_host::OpenNaClExecutable(this, extension_info_map_, 206 render_view_id, file_url, reply_msg); 207 } 208 #endif 209