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
|
// 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.
#ifndef COMPONENTS_NACL_BROWSER_PNACL_HOST_H_
#define COMPONENTS_NACL_BROWSER_PNACL_HOST_H_
#include <map>
#include "base/callback_forward.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.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 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::Callback<void(base::PlatformFile)> TempFileCallback;
typedef base::Callback<void(base::PlatformFile, bool is_hit)> NexeFdCallback;
static PnaclHost* GetInstance();
PnaclHost();
~PnaclHost();
// 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::GetFileHandleForProcess) 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 render_view_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,
const base::Closure& callback);
// Return the number of tracked translations or FD requests currently pending.
size_t pending_translations() { return pending_translations_.size(); }
private:
// 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.
friend struct DefaultSingletonTraits<PnaclHost>;
friend class pnacl::PnaclHostTest;
enum CacheState {
CacheUninitialized,
CacheInitializing,
CacheReady
};
class PendingTranslation {
public:
PendingTranslation();
~PendingTranslation();
base::ProcessHandle process_handle;
int render_view_id;
base::PlatformFile 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;
static bool TranslationMayBeCached(
const PendingTranslationMap::iterator& entry);
void InitForTest(base::FilePath temp_dir);
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::PlatformFile fd);
void CheckCacheQueryReady(const PendingTranslationMap::iterator& entry);
// GetNexeFd miss path
void ReturnMiss(const PendingTranslationMap::iterator& entry);
static scoped_refptr<net::DrainableIOBuffer> CopyFileToBuffer(
base::PlatformFile fd);
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
static int CopyBufferToFile(base::PlatformFile fd,
scoped_refptr<net::DrainableIOBuffer> buffer);
void OnBufferCopiedToTempFile(const TranslationID& id, int file_error);
void OnEntriesDoomed(const base::Closure& callback, int net_error);
void DeInitIfSafe();
// Operations which are pending with the cache backend, which we should
// wait for before destroying it (see comment on DeInitIfSafe).
int pending_backend_operations_;
CacheState cache_state_;
base::FilePath temp_dir_;
scoped_ptr<pnacl::PnaclTranslationCache> disk_cache_;
PendingTranslationMap pending_translations_;
base::ThreadChecker thread_checker_;
base::WeakPtrFactory<PnaclHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PnaclHost);
};
} // namespace pnacl
#endif // COMPONENTS_NACL_BROWSER_PNACL_HOST_H_
|