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