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 #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