Home | History | Annotate | Download | only in browser
      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