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