File: pnacl_host.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (200 lines) | stat: -rw-r--r-- 7,891 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_NACL_BROWSER_PNACL_HOST_H_
#define COMPONENTS_NACL_BROWSER_PNACL_HOST_H_

#include <stddef.h>

#include <map>
#include <memory>

#include "base/files/file.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_checker.h"
#include "components/nacl/browser/nacl_file_host.h"
#include "components/nacl/common/pnacl_types.h"
#include "ipc/ipc_platform_file.h"

namespace net {
class DrainableIOBuffer;
}

namespace pnacl {

class PnaclHostTest;
class PnaclHostTestDisk;
class PnaclTranslationCache;

// Shared state (translation cache) and common utilities (temp file creation)
// for all PNaCl translations. Unless otherwise specified, all methods should be
// called on the IO thread.
class PnaclHost {
 public:
  typedef base::RepeatingCallback<void(base::File)> TempFileCallback;
  typedef base::RepeatingCallback<void(const base::File&, bool is_hit)>
      NexeFdCallback;

  // Gets the PnaclHost singleton instance (creating it if necessary).
  // PnaclHost is a singleton because there is only one translation cache, and
  // so that the BrowsingDataRemover can clear it even if no translation has
  // ever been started.
  static PnaclHost* GetInstance();

  PnaclHost(const PnaclHost&) = delete;
  PnaclHost& operator=(const PnaclHost&) = delete;

  // The PnaclHost instance is intentionally leaked on shutdown. DeInitIfSafe()
  // attempts to cleanup |disk_cache_| earlier, but if it fails to do so in
  // time, it will be too late when AtExitManager kicks in anway so subscribing
  // to it is useless.
  ~PnaclHost() = delete;

  // Initialize cache backend. GetNexeFd will also initialize the backend if
  // necessary, but calling Init ahead of time will minimize the latency.
  void Init();

  // Creates a temporary file that will be deleted when the last handle
  // is closed, or earlier. Returns a PlatformFile handle.
  void CreateTemporaryFile(TempFileCallback cb);

  // Create a temporary file, which will be deleted by the time the last
  // handle is closed (or earlier on POSIX systems), to use for the nexe
  // with the cache information given in |cache_info|. The specific instance
  // is identified by the combination of |render_process_id| and |pp_instance|.
  // Returns by calling |cb| with a PlatformFile handle.
  // If the nexe is already present
  // in the cache, |is_hit| is set to true and the contents of the nexe
  // have been copied into the temporary file. Otherwise |is_hit| is set to
  // false and the temporary file will be writeable.
  // Currently the implementation is a stub, which always sets is_hit to false
  // and calls the implementation of CreateTemporaryFile.
  // If the cache request was a miss, the caller is expected to call
  // TranslationFinished after it finishes translation to allow the nexe to be
  // stored in the cache.
  // The returned temp fd may be closed at any time by PnaclHost, so it should
  // be duplicated (e.g. with IPC::GetPlatformFileForTransit) before the
  // callback returns.
  // If |is_incognito| is true, the nexe will not be stored
  // in the cache, but the renderer is still expected to call
  // TranslationFinished.
  void GetNexeFd(int render_process_id,
                 int pp_instance,
                 bool is_incognito,
                 const nacl::PnaclCacheInfo& cache_info,
                 const NexeFdCallback& cb);

  // Called after the translation of a pexe instance identified by
  // |render_process_id| and |pp_instance| finishes. If |success| is true,
  // store the nexe translated for the instance in the cache.
  void TranslationFinished(int render_process_id,
                           int pp_instance,
                           bool success);

  // Called when the renderer identified by |render_process_id| is closing.
  // Clean up any outstanding translations for that renderer. If there are no
  // more pending translations, the backend is freed, allowing it to flush.
  void RendererClosing(int render_process_id);

  // Doom all entries between |initial_time| and |end_time|. Like disk_cache_,
  // PnaclHost supports supports unbounded deletes in either direction by using
  // null Time values for either argument. |callback| will be called on the UI
  // thread when finished.
  void ClearTranslationCacheEntriesBetween(base::Time initial_time,
                                           base::Time end_time,
                                           base::OnceClosure callback);

  // Return the number of tracked translations or FD requests currently pending.
  size_t pending_translations() {
    DCHECK(thread_checker_.CalledOnValidThread());
    return pending_translations_.size();
  }

 private:
  friend class FileProxy;
  friend class PnaclHostTest;
  friend class PnaclHostTestDisk;
  enum CacheState {
    CacheUninitialized,
    CacheInitializing,
    CacheReady
  };
  class PendingTranslation {
   public:
    PendingTranslation();
    PendingTranslation(const PendingTranslation& other);
    ~PendingTranslation();
    base::ProcessHandle process_handle;
    raw_ptr<base::File> nexe_fd;
    bool got_nexe_fd;
    bool got_cache_reply;
    bool got_cache_hit;
    bool is_incognito;
    scoped_refptr<net::DrainableIOBuffer> nexe_read_buffer;
    NexeFdCallback callback;
    std::string cache_key;
    nacl::PnaclCacheInfo cache_info;
  };

  typedef std::pair<int, int> TranslationID;
  typedef std::map<TranslationID, PendingTranslation> PendingTranslationMap;

  PnaclHost();

  static bool TranslationMayBeCached(
      const PendingTranslationMap::iterator& entry);

  void InitForTest(base::FilePath temp_dir, bool in_memory);
  void OnCacheInitialized(int net_error);

  static void DoCreateTemporaryFile(base::FilePath temp_dir_,
                                    TempFileCallback cb);

  // GetNexeFd common steps
  void SendCacheQueryAndTempFileRequest(const std::string& key,
                                        const TranslationID& id);
  void OnCacheQueryReturn(const TranslationID& id,
                          int net_error,
                          scoped_refptr<net::DrainableIOBuffer> buffer);
  void OnTempFileReturn(const TranslationID& id, base::File file);
  void CheckCacheQueryReady(const PendingTranslationMap::iterator& entry);

  // GetNexeFd miss path
  void ReturnMiss(const PendingTranslationMap::iterator& entry);
  static scoped_refptr<net::DrainableIOBuffer> CopyFileToBuffer(
      std::unique_ptr<base::File> file);
  void StoreTranslatedNexe(TranslationID id,
                           scoped_refptr<net::DrainableIOBuffer>);
  void OnTranslatedNexeStored(const TranslationID& id, int net_error);
  void RequeryMatchingTranslations(const std::string& key);

  // GetNexeFd hit path
  void OnBufferCopiedToTempFile(const TranslationID& id,
                                std::unique_ptr<base::File> file,
                                int file_error);

  void OnEntriesDoomed(base::OnceClosure callback, int net_error);

  void DeInitIfSafe();

  scoped_refptr<base::SequencedTaskRunner> file_task_runner_ =
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_VISIBLE});

  // Operations which are pending with the cache backend, which we should
  // wait for before destroying it (see comment on DeInitIfSafe).
  int pending_backend_operations_ = 0;
  CacheState cache_state_ = CacheUninitialized;
  base::FilePath temp_dir_;
  std::unique_ptr<PnaclTranslationCache> disk_cache_;
  PendingTranslationMap pending_translations_;
  base::ThreadChecker thread_checker_;
};

}  // namespace pnacl

#endif  // COMPONENTS_NACL_BROWSER_PNACL_HOST_H_