Home | History | Annotate | Download | only in renderer
      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