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