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 "pnacl_translation_resource_host.h" 6 7 #ifndef DISABLE_NACL 8 #include "components/nacl/common/nacl_host_messages.h" 9 #include "ppapi/c/pp_errors.h" 10 #include "ppapi/shared_impl/ppapi_globals.h" 11 12 using ppapi::TrackedCallback; 13 using ppapi::PpapiGlobals; 14 15 PnaclTranslationResourceHost::CacheRequestInfo::CacheRequestInfo( 16 PP_Bool* hit, 17 PP_FileHandle* handle, 18 scoped_refptr<TrackedCallback> cb) 19 : is_hit(hit), file_handle(handle), callback(cb) {} 20 21 PnaclTranslationResourceHost::CacheRequestInfo::~CacheRequestInfo() {} 22 23 PnaclTranslationResourceHost::PnaclTranslationResourceHost( 24 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) 25 : io_message_loop_(io_message_loop), channel_(NULL) {} 26 27 PnaclTranslationResourceHost::~PnaclTranslationResourceHost() { 28 DCHECK(io_message_loop_->BelongsToCurrentThread()); 29 CleanupCacheRequests(); 30 } 31 32 void PnaclTranslationResourceHost::OnFilterAdded(IPC::Channel* channel) { 33 DCHECK(io_message_loop_->BelongsToCurrentThread()); 34 channel_ = channel; 35 } 36 37 void PnaclTranslationResourceHost::OnFilterRemoved() { 38 DCHECK(io_message_loop_->BelongsToCurrentThread()); 39 channel_ = NULL; 40 } 41 42 void PnaclTranslationResourceHost::OnChannelClosing() { 43 DCHECK(io_message_loop_->BelongsToCurrentThread()); 44 channel_ = NULL; 45 } 46 47 bool PnaclTranslationResourceHost::OnMessageReceived( 48 const IPC::Message& message) { 49 DCHECK(io_message_loop_->BelongsToCurrentThread()); 50 bool handled = true; 51 IPC_BEGIN_MESSAGE_MAP(PnaclTranslationResourceHost, message) 52 IPC_MESSAGE_HANDLER(NaClViewMsg_NexeTempFileReply, OnNexeTempFileReply) 53 IPC_MESSAGE_UNHANDLED(handled = false) 54 IPC_END_MESSAGE_MAP() 55 return handled; 56 } 57 58 void PnaclTranslationResourceHost::RequestNexeFd( 59 int render_view_id, 60 PP_Instance instance, 61 const nacl::PnaclCacheInfo& cache_info, 62 PP_Bool* is_hit, 63 PP_FileHandle* file_handle, 64 scoped_refptr<TrackedCallback> callback) { 65 DCHECK(PpapiGlobals::Get()-> 66 GetMainThreadMessageLoop()->BelongsToCurrentThread()); 67 io_message_loop_->PostTask( 68 FROM_HERE, 69 base::Bind(&PnaclTranslationResourceHost::SendRequestNexeFd, 70 this, 71 render_view_id, 72 instance, 73 cache_info, 74 is_hit, 75 file_handle, 76 callback)); 77 return; 78 } 79 80 void PnaclTranslationResourceHost::SendRequestNexeFd( 81 int render_view_id, 82 PP_Instance instance, 83 const nacl::PnaclCacheInfo& cache_info, 84 PP_Bool* is_hit, 85 PP_FileHandle* file_handle, 86 scoped_refptr<TrackedCallback> callback) { 87 DCHECK(io_message_loop_->BelongsToCurrentThread()); 88 if (!channel_ || !channel_->Send(new NaClHostMsg_NexeTempFileRequest( 89 render_view_id, instance, cache_info))) { 90 PpapiGlobals::Get()->GetMainThreadMessageLoop() 91 ->PostTask(FROM_HERE, 92 base::Bind(&TrackedCallback::Run, 93 callback, 94 static_cast<int32_t>(PP_ERROR_FAILED))); 95 return; 96 } 97 pending_cache_requests_.insert(std::make_pair( 98 instance, CacheRequestInfo(is_hit, file_handle, callback))); 99 } 100 101 void PnaclTranslationResourceHost::ReportTranslationFinished( 102 PP_Instance instance, 103 PP_Bool success) { 104 DCHECK(PpapiGlobals::Get()-> 105 GetMainThreadMessageLoop()->BelongsToCurrentThread()); 106 io_message_loop_->PostTask( 107 FROM_HERE, 108 base::Bind(&PnaclTranslationResourceHost::SendReportTranslationFinished, 109 this, 110 instance, 111 success)); 112 return; 113 } 114 115 void PnaclTranslationResourceHost::SendReportTranslationFinished( 116 PP_Instance instance, 117 PP_Bool success) { 118 DCHECK(io_message_loop_->BelongsToCurrentThread()); 119 // If the channel is closed or we have been detached, we are probably shutting 120 // down, so just don't send anything. 121 if (!channel_) 122 return; 123 DCHECK(pending_cache_requests_.count(instance) == 0); 124 channel_->Send(new NaClHostMsg_ReportTranslationFinished(instance, 125 PP_ToBool(success))); 126 } 127 128 void PnaclTranslationResourceHost::OnNexeTempFileReply( 129 PP_Instance instance, 130 bool is_hit, 131 IPC::PlatformFileForTransit file) { 132 DCHECK(io_message_loop_->BelongsToCurrentThread()); 133 CacheRequestInfoMap::iterator it = pending_cache_requests_.find(instance); 134 int32_t status = PP_ERROR_FAILED; 135 // Handle the expected successful case first. 136 if (it != pending_cache_requests_.end() && 137 !(file == IPC::InvalidPlatformFileForTransit()) && 138 TrackedCallback::IsPending(it->second.callback)) { 139 *it->second.is_hit = PP_FromBool(is_hit); 140 *it->second.file_handle = IPC::PlatformFileForTransitToPlatformFile(file); 141 status = PP_OK; 142 } 143 if (it == pending_cache_requests_.end()) { 144 DLOG(ERROR) << "Could not find pending request for reply"; 145 } else { 146 PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( 147 FROM_HERE, 148 base::Bind(&TrackedCallback::Run, it->second.callback, status)); 149 pending_cache_requests_.erase(it); 150 } 151 if (file == IPC::InvalidPlatformFileForTransit()) { 152 DLOG(ERROR) << "Got invalid platformfilefortransit"; 153 } else if (status != PP_OK) { 154 base::ClosePlatformFile(IPC::PlatformFileForTransitToPlatformFile(file)); 155 } 156 } 157 158 void PnaclTranslationResourceHost::CleanupCacheRequests() { 159 DCHECK(io_message_loop_->BelongsToCurrentThread()); 160 for (CacheRequestInfoMap::iterator it = pending_cache_requests_.begin(); 161 it != pending_cache_requests_.end(); 162 ++it) { 163 it->second.callback->PostAbort(); 164 } 165 pending_cache_requests_.clear(); 166 } 167 168 #endif // DISABLE_NACL 169