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