• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef COMPONENTS_NACL_BROWSER_PNACL_HOST_H_
6 #define COMPONENTS_NACL_BROWSER_PNACL_HOST_H_
7 
8 #include <map>
9 
10 #include "base/callback_forward.h"
11 #include "base/files/file.h"
12 #include "base/memory/singleton.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/threading/thread_checker.h"
15 #include "components/nacl/browser/nacl_file_host.h"
16 #include "components/nacl/common/pnacl_types.h"
17 #include "ipc/ipc_platform_file.h"
18 
19 namespace net {
20 class DrainableIOBuffer;
21 }
22 
23 namespace pnacl {
24 
25 class PnaclHostTest;
26 class PnaclHostTestDisk;
27 class PnaclTranslationCache;
28 
29 // Shared state (translation cache) and common utilities (temp file creation)
30 // for all PNaCl translations. Unless otherwise specified, all methods should be
31 // called on the IO thread.
32 class PnaclHost {
33  public:
34   typedef base::Callback<void(base::File)> TempFileCallback;
35   typedef base::Callback<void(const base::File&, bool is_hit)> NexeFdCallback;
36 
37   static PnaclHost* GetInstance();
38 
39   PnaclHost();
40   ~PnaclHost();
41 
42   // Initialize cache backend. GetNexeFd will also initialize the backend if
43   // necessary, but calling Init ahead of time will minimize the latency.
44   void Init();
45 
46   // Creates a temporary file that will be deleted when the last handle
47   // is closed, or earlier. Returns a PlatformFile handle.
48   void CreateTemporaryFile(TempFileCallback cb);
49 
50   // Create a temporary file, which will be deleted by the time the last
51   // handle is closed (or earlier on POSIX systems), to use for the nexe
52   // with the cache information given in |cache_info|. The specific instance
53   // is identified by the combination of |render_process_id| and |pp_instance|.
54   // Returns by calling |cb| with a PlatformFile handle.
55   // If the nexe is already present
56   // in the cache, |is_hit| is set to true and the contents of the nexe
57   // have been copied into the temporary file. Otherwise |is_hit| is set to
58   // false and the temporary file will be writeable.
59   // Currently the implementation is a stub, which always sets is_hit to false
60   // and calls the implementation of CreateTemporaryFile.
61   // If the cache request was a miss, the caller is expected to call
62   // TranslationFinished after it finishes translation to allow the nexe to be
63   // stored in the cache.
64   // The returned temp fd may be closed at any time by PnaclHost, so it should
65   // be duplicated (e.g. with IPC::GetFileHandleForProcess) before the callback
66   // returns.
67   // If |is_incognito| is true, the nexe will not be stored
68   // in the cache, but the renderer is still expected to call
69   // TranslationFinished.
70   void GetNexeFd(int render_process_id,
71                  int render_view_id,
72                  int pp_instance,
73                  bool is_incognito,
74                  const nacl::PnaclCacheInfo& cache_info,
75                  const NexeFdCallback& cb);
76 
77   // Called after the translation of a pexe instance identified by
78   // |render_process_id| and |pp_instance| finishes. If |success| is true,
79   // store the nexe translated for the instance in the cache.
80   void TranslationFinished(int render_process_id,
81                            int pp_instance,
82                            bool success);
83 
84   // Called when the renderer identified by |render_process_id| is closing.
85   // Clean up any outstanding translations for that renderer. If there are no
86   // more pending translations, the backend is freed, allowing it to flush.
87   void RendererClosing(int render_process_id);
88 
89   // Doom all entries between |initial_time| and |end_time|. Like disk_cache_,
90   // PnaclHost supports supports unbounded deletes in either direction by using
91   // null Time values for either argument. |callback| will be called on the UI
92   // thread when finished.
93   void ClearTranslationCacheEntriesBetween(base::Time initial_time,
94                                            base::Time end_time,
95                                            const base::Closure& callback);
96 
97   // Return the number of tracked translations or FD requests currently pending.
pending_translations()98   size_t pending_translations() { return pending_translations_.size(); }
99 
100  private:
101   // PnaclHost is a singleton because there is only one translation cache, and
102   // so that the BrowsingDataRemover can clear it even if no translation has
103   // ever been started.
104   friend struct DefaultSingletonTraits<PnaclHost>;
105   friend class FileProxy;
106   friend class pnacl::PnaclHostTest;
107   friend class pnacl::PnaclHostTestDisk;
108   enum CacheState {
109     CacheUninitialized,
110     CacheInitializing,
111     CacheReady
112   };
113   class PendingTranslation {
114    public:
115     PendingTranslation();
116     ~PendingTranslation();
117     base::ProcessHandle process_handle;
118     int render_view_id;
119     base::File* nexe_fd;
120     bool got_nexe_fd;
121     bool got_cache_reply;
122     bool got_cache_hit;
123     bool is_incognito;
124     scoped_refptr<net::DrainableIOBuffer> nexe_read_buffer;
125     NexeFdCallback callback;
126     std::string cache_key;
127     nacl::PnaclCacheInfo cache_info;
128   };
129 
130   typedef std::pair<int, int> TranslationID;
131   typedef std::map<TranslationID, PendingTranslation> PendingTranslationMap;
132   static bool TranslationMayBeCached(
133       const PendingTranslationMap::iterator& entry);
134 
135   void InitForTest(base::FilePath temp_dir, bool in_memory);
136   void OnCacheInitialized(int net_error);
137 
138   static void DoCreateTemporaryFile(base::FilePath temp_dir_,
139                                     TempFileCallback cb);
140 
141   // GetNexeFd common steps
142   void SendCacheQueryAndTempFileRequest(const std::string& key,
143                                         const TranslationID& id);
144   void OnCacheQueryReturn(const TranslationID& id,
145                           int net_error,
146                           scoped_refptr<net::DrainableIOBuffer> buffer);
147   void OnTempFileReturn(const TranslationID& id, base::File file);
148   void CheckCacheQueryReady(const PendingTranslationMap::iterator& entry);
149 
150   // GetNexeFd miss path
151   void ReturnMiss(const PendingTranslationMap::iterator& entry);
152   static scoped_refptr<net::DrainableIOBuffer> CopyFileToBuffer(
153       scoped_ptr<base::File> file);
154   void StoreTranslatedNexe(TranslationID id,
155                            scoped_refptr<net::DrainableIOBuffer>);
156   void OnTranslatedNexeStored(const TranslationID& id, int net_error);
157   void RequeryMatchingTranslations(const std::string& key);
158 
159   // GetNexeFd hit path
160   void OnBufferCopiedToTempFile(const TranslationID& id,
161                                 scoped_ptr<base::File> file,
162                                 int file_error);
163 
164   void OnEntriesDoomed(const base::Closure& callback, int net_error);
165 
166   void DeInitIfSafe();
167 
168   // Operations which are pending with the cache backend, which we should
169   // wait for before destroying it (see comment on DeInitIfSafe).
170   int pending_backend_operations_;
171   CacheState cache_state_;
172   base::FilePath temp_dir_;
173   scoped_ptr<pnacl::PnaclTranslationCache> disk_cache_;
174   PendingTranslationMap pending_translations_;
175   base::ThreadChecker thread_checker_;
176   base::WeakPtrFactory<PnaclHost> weak_factory_;
177   DISALLOW_COPY_AND_ASSIGN(PnaclHost);
178 };
179 
180 }  // namespace pnacl
181 
182 #endif  // COMPONENTS_NACL_BROWSER_PNACL_HOST_H_
183