// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "pnacl_translation_resource_host.h" #ifndef DISABLE_NACL #include "components/nacl/common/nacl_host_messages.h" #include "ppapi/c/pp_errors.h" #include "ppapi/shared_impl/ppapi_globals.h" using ppapi::TrackedCallback; using ppapi::PpapiGlobals; PnaclTranslationResourceHost::CacheRequestInfo::CacheRequestInfo( PP_Bool* hit, PP_FileHandle* handle, scoped_refptr cb) : is_hit(hit), file_handle(handle), callback(cb) {} PnaclTranslationResourceHost::CacheRequestInfo::~CacheRequestInfo() {} PnaclTranslationResourceHost::PnaclTranslationResourceHost( const scoped_refptr& io_message_loop) : io_message_loop_(io_message_loop), channel_(NULL) {} PnaclTranslationResourceHost::~PnaclTranslationResourceHost() { DCHECK(io_message_loop_->BelongsToCurrentThread()); CleanupCacheRequests(); } void PnaclTranslationResourceHost::OnFilterAdded(IPC::Channel* channel) { DCHECK(io_message_loop_->BelongsToCurrentThread()); channel_ = channel; } void PnaclTranslationResourceHost::OnFilterRemoved() { DCHECK(io_message_loop_->BelongsToCurrentThread()); channel_ = NULL; } void PnaclTranslationResourceHost::OnChannelClosing() { DCHECK(io_message_loop_->BelongsToCurrentThread()); channel_ = NULL; } bool PnaclTranslationResourceHost::OnMessageReceived( const IPC::Message& message) { DCHECK(io_message_loop_->BelongsToCurrentThread()); bool handled = true; IPC_BEGIN_MESSAGE_MAP(PnaclTranslationResourceHost, message) IPC_MESSAGE_HANDLER(NaClViewMsg_NexeTempFileReply, OnNexeTempFileReply) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void PnaclTranslationResourceHost::RequestNexeFd( int render_view_id, PP_Instance instance, const nacl::PnaclCacheInfo& cache_info, PP_Bool* is_hit, PP_FileHandle* file_handle, scoped_refptr callback) { DCHECK(PpapiGlobals::Get()-> GetMainThreadMessageLoop()->BelongsToCurrentThread()); io_message_loop_->PostTask( FROM_HERE, base::Bind(&PnaclTranslationResourceHost::SendRequestNexeFd, this, render_view_id, instance, cache_info, is_hit, file_handle, callback)); return; } void PnaclTranslationResourceHost::SendRequestNexeFd( int render_view_id, PP_Instance instance, const nacl::PnaclCacheInfo& cache_info, PP_Bool* is_hit, PP_FileHandle* file_handle, scoped_refptr callback) { DCHECK(io_message_loop_->BelongsToCurrentThread()); if (!channel_ || !channel_->Send(new NaClHostMsg_NexeTempFileRequest( render_view_id, instance, cache_info))) { PpapiGlobals::Get()->GetMainThreadMessageLoop() ->PostTask(FROM_HERE, base::Bind(&TrackedCallback::Run, callback, static_cast(PP_ERROR_FAILED))); return; } pending_cache_requests_.insert(std::make_pair( instance, CacheRequestInfo(is_hit, file_handle, callback))); } void PnaclTranslationResourceHost::ReportTranslationFinished( PP_Instance instance, PP_Bool success) { DCHECK(PpapiGlobals::Get()-> GetMainThreadMessageLoop()->BelongsToCurrentThread()); io_message_loop_->PostTask( FROM_HERE, base::Bind(&PnaclTranslationResourceHost::SendReportTranslationFinished, this, instance, success)); return; } void PnaclTranslationResourceHost::SendReportTranslationFinished( PP_Instance instance, PP_Bool success) { DCHECK(io_message_loop_->BelongsToCurrentThread()); // If the channel is closed or we have been detached, we are probably shutting // down, so just don't send anything. if (!channel_) return; DCHECK(pending_cache_requests_.count(instance) == 0); channel_->Send(new NaClHostMsg_ReportTranslationFinished(instance, PP_ToBool(success))); } void PnaclTranslationResourceHost::OnNexeTempFileReply( PP_Instance instance, bool is_hit, IPC::PlatformFileForTransit file) { DCHECK(io_message_loop_->BelongsToCurrentThread()); CacheRequestInfoMap::iterator it = pending_cache_requests_.find(instance); int32_t status = PP_ERROR_FAILED; // Handle the expected successful case first. if (it != pending_cache_requests_.end() && !(file == IPC::InvalidPlatformFileForTransit()) && TrackedCallback::IsPending(it->second.callback)) { *it->second.is_hit = PP_FromBool(is_hit); *it->second.file_handle = IPC::PlatformFileForTransitToPlatformFile(file); status = PP_OK; } if (it == pending_cache_requests_.end()) { DLOG(ERROR) << "Could not find pending request for reply"; } else { PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( FROM_HERE, base::Bind(&TrackedCallback::Run, it->second.callback, status)); pending_cache_requests_.erase(it); } if (file == IPC::InvalidPlatformFileForTransit()) { DLOG(ERROR) << "Got invalid platformfilefortransit"; } else if (status != PP_OK) { base::ClosePlatformFile(IPC::PlatformFileForTransitToPlatformFile(file)); } } void PnaclTranslationResourceHost::CleanupCacheRequests() { DCHECK(io_message_loop_->BelongsToCurrentThread()); for (CacheRequestInfoMap::iterator it = pending_cache_requests_.begin(); it != pending_cache_requests_.end(); ++it) { it->second.callback->PostAbort(); } pending_cache_requests_.clear(); } #endif // DISABLE_NACL