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