1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/nacl_file_host.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/path_service.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "components/nacl/browser/nacl_browser.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/nacl_browser_delegate.h" 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/nacl_host_message_filter.h" 17a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "components/nacl/common/nacl_host_messages.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/render_view_host.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/site_instance.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ipc/ipc_platform_file.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using content::BrowserThread; 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Force a prefix to prevent user from opening "magic" files. 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* kExpectedFilePrefix = "pnacl_public_"; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Restrict PNaCl file lengths to reduce likelyhood of hitting bugs 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// in file name limit error-handling-code-paths, etc. 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kMaxFileLength = 40; 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NotifyRendererOfError( 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) nacl::NaClHostMessageFilter* nacl_host_message_filter, 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IPC::Message* reply_msg) { 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reply_msg->set_reply_error(); 387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl_host_message_filter->Send(reply_msg); 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtypedef void (*WriteFileInfoReply)(IPC::Message* reply_msg, 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC::PlatformFileForTransit file_desc, 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint64 file_token_lo, 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint64 file_token_hi); 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid DoRegisterOpenedNaClExecutableFile( 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::File file, 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::FilePath file_path, 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC::Message* reply_msg, 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WriteFileInfoReply write_reply_message) { 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // IO thread owns the NaClBrowser singleton. 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint64 file_token_lo = 0; 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint64 file_token_hi = 0; 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch nacl_browser->PutFilePath(file_path, &file_token_lo, &file_token_hi); 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC::PlatformFileForTransit file_desc = IPC::TakeFileHandleForProcess( 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch file.Pass(), 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch nacl_host_message_filter->PeerHandle()); 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch write_reply_message(reply_msg, file_desc, file_token_lo, file_token_hi); 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch nacl_host_message_filter->Send(reply_msg); 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DoOpenPnaclFile( 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& filename, 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool is_executable, 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IPC::Message* reply_msg) { 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath full_filepath; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // PNaCl must be installed. 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath pnacl_dir; 780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!nacl::NaClBrowser::GetDelegate()->GetPnaclDirectory(&pnacl_dir) || 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !base::PathExists(pnacl_dir)) { 802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Do some validation. 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!nacl_file_host::PnaclCanOpenFile(filename, &full_filepath)) { 867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::File file_to_open = nacl::OpenNaClReadExecImpl(full_filepath, 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch is_executable); 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!file_to_open.IsValid()) { 937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // This function is running on the blocking pool, but the path needs to be 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // registered in a structure owned by the IO thread. 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Not all PNaCl files are executable. Only register those that are 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // executable in the NaCl file_path cache. 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (is_executable) { 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserThread::PostTask( 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserThread::IO, FROM_HERE, 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&DoRegisterOpenedNaClExecutableFile, 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch nacl_host_message_filter, 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Passed(file_to_open.Pass()), full_filepath, reply_msg, 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static_cast<WriteFileInfoReply>( 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams))); 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC::PlatformFileForTransit target_desc = 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPC::TakeFileHandleForProcess(file_to_open.Pass(), 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch nacl_host_message_filter->PeerHandle()); 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint64_t dummy_file_token = 0; 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams( 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch reply_msg, target_desc, dummy_file_token, dummy_file_token); 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch nacl_host_message_filter->Send(reply_msg); 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Convert the file URL into a file descriptor. 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This function is security sensitive. Be sure to check with a security 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// person before you modify it. 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DoOpenNaClExecutableOnThreadPool( 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const GURL& file_url, 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IPC::Message* reply_msg) { 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath file_path; 1300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!nacl::NaClBrowser::GetDelegate()->MapUrlToLocalFilePath( 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) file_url, 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) true /* use_blocking_api */, 133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) nacl_host_message_filter->profile_directory(), 134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) &file_path)) { 1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::File file = nacl::OpenNaClReadExecImpl(file_path, 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch true /* is_executable */); 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (file.IsValid()) { 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // This function is running on the blocking pool, but the path needs to be 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // registered in a structure owned by the IO thread. 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BrowserThread::PostTask( 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BrowserThread::IO, FROM_HERE, 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind( 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &DoRegisterOpenedNaClExecutableFile, 1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl_host_message_filter, 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Passed(file.Pass()), file_path, reply_msg, 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static_cast<WriteFileInfoReply>( 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NaClHostMsg_OpenNaClExecutable::WriteReplyParams))); 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace nacl_file_host { 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GetReadonlyPnaclFd( 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& filename, 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool is_executable, 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IPC::Message* reply_msg) { 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!BrowserThread::PostBlockingPoolTask( 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&DoOpenPnaclFile, 1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl_host_message_filter, 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) filename, 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch is_executable, 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reply_msg))) { 1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This function is security sensitive. Be sure to check with a security 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// person before you modify it. 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool PnaclCanOpenFile(const std::string& filename, 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath* file_to_open) { 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (filename.length() > kMaxFileLength) 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (filename.empty()) 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Restrict character set of the file name to something really simple 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // (a-z, 0-9, and underscores). 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < filename.length(); ++i) { 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) char charAt = filename[i]; 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (charAt < 'a' || charAt > 'z') 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (charAt < '0' || charAt > '9') 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (charAt != '_') 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // PNaCl must be installed. 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath pnacl_dir; 2000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!nacl::NaClBrowser::GetDelegate()->GetPnaclDirectory(&pnacl_dir) || 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pnacl_dir.empty()) 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Prepend the prefix to restrict files to a whitelisted set. 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath full_path = pnacl_dir.AppendASCII( 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(kExpectedFilePrefix) + filename); 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *file_to_open = full_path; 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void OpenNaClExecutable( 212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int render_view_id, 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const GURL& file_url, 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IPC::Message* reply_msg) { 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BrowserThread::PostTask( 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BrowserThread::UI, FROM_HERE, 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind( 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &OpenNaClExecutable, 2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl_host_message_filter, 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) render_view_id, file_url, reply_msg)); 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Make sure render_view_id is valid and that the URL is a part of the 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // render view's site. Without these checks, apps could probe the extension 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // directory or run NaCl code from other extensions. 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::RenderViewHost* rvh = content::RenderViewHost::FromID( 2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl_host_message_filter->render_process_id(), render_view_id); 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!rvh) { 2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl_host_message_filter->BadMessageReceived(); // Kill the renderer. 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::SiteInstance* site_instance = rvh->GetSiteInstance(); 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!content::SiteInstance::IsSameWebSite(site_instance->GetBrowserContext(), 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) site_instance->GetSiteURL(), 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) file_url)) { 2397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The URL is part of the current app. Now query the extension system for the 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // file path and convert that to a file descriptor. This should be done on a 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // blocking pool thread. 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!BrowserThread::PostBlockingPoolTask( 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind( 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &DoOpenNaClExecutableOnThreadPool, 2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl_host_message_filter, 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) file_url, reply_msg))) { 2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace nacl_file_host 257