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