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 CHROME_BROWSER_NACL_HOST_PNACL_HOST_H_ 6 #define CHROME_BROWSER_NACL_HOST_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 "chrome/browser/nacl_host/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 class PnaclHostTest; 24 class PnaclTranslationCache; 25 } 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 129 void InitForTest(base::FilePath temp_dir); 130 void OnCacheInitialized(int net_error); 131 132 static base::PlatformFile DoCreateTemporaryFile(base::FilePath temp_dir_); 133 134 // GetNexeFd common steps 135 void SendCacheQueryAndTempFileRequest(const std::string& key, 136 const TranslationID& id); 137 void OnCacheQueryReturn(const TranslationID& id, 138 int net_error, 139 scoped_refptr<net::DrainableIOBuffer> buffer); 140 void OnTempFileReturn(const TranslationID& id, base::PlatformFile fd); 141 void CheckCacheQueryReady(const PendingTranslationMap::iterator& entry); 142 143 // GetNexeFd miss path 144 void ReturnMiss(const PendingTranslationMap::iterator& entry); 145 static scoped_refptr<net::DrainableIOBuffer> CopyFileToBuffer( 146 base::PlatformFile fd); 147 void StoreTranslatedNexe(TranslationID id, 148 scoped_refptr<net::DrainableIOBuffer>); 149 void OnTranslatedNexeStored(const TranslationID& id, int net_error); 150 void RequeryMatchingTranslations(const std::string& key); 151 152 // GetNexeFd hit path 153 static int CopyBufferToFile(base::PlatformFile fd, 154 scoped_refptr<net::DrainableIOBuffer> buffer); 155 void OnBufferCopiedToTempFile(const TranslationID& id, int file_error); 156 157 static void OnEntriesDoomed(const base::Closure& callback, int net_error); 158 159 CacheState cache_state_; 160 base::FilePath temp_dir_; 161 scoped_ptr<pnacl::PnaclTranslationCache> disk_cache_; 162 PendingTranslationMap pending_translations_; 163 base::ThreadChecker thread_checker_; 164 base::WeakPtrFactory<PnaclHost> weak_factory_; 165 DISALLOW_COPY_AND_ASSIGN(PnaclHost); 166 }; 167 168 #endif // CHROME_BROWSER_NACL_HOST_PNACL_HOST_H_ 169