Home | History | Annotate | Download | only in updater
      1 // Copyright 2014 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_EXTENSIONS_UPDATER_LOCAL_EXTENSION_CACHE_H_
      6 #define CHROME_BROWSER_EXTENSIONS_UPDATER_LOCAL_EXTENSION_CACHE_H_
      7 
      8 #include <map>
      9 #include <string>
     10 
     11 #include "base/callback_forward.h"
     12 #include "base/files/file_path.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/memory/weak_ptr.h"
     15 #include "base/time/time.h"
     16 
     17 namespace extensions {
     18 
     19 // Cache .crx files in some local dir for future use. Cache keeps only latest
     20 // version of the extensions. Only one instance of LocalExtensionCache can work
     21 // with the same directory. But LocalExtensionCache instance can be shared
     22 // between multiple clients. Public interface can be used only from UI thread.
     23 class LocalExtensionCache {
     24  public:
     25   // Callback invoked on UI thread when PutExtension is completed.
     26   typedef base::Callback<void(const base::FilePath& file_path,
     27                               bool file_ownership_passed)> PutExtensionCallback;
     28 
     29   // |cache_dir| - directory that will be used for caching CRX files.
     30   // |max_cache_size| - maximum disk space that cache can use, 0 means no limit.
     31   // |max_cache_age| - maximum age that unused item can be kept in cache, 0 age
     32   // means that all unused cache items will be removed on Shutdown.
     33   // All file I/O is done via the |backend_task_runner|.
     34   LocalExtensionCache(const base::FilePath& cache_dir,
     35                       uint64 max_cache_size,
     36                       const base::TimeDelta& max_cache_age,
     37                       const scoped_refptr<base::SequencedTaskRunner>&
     38                           backend_task_runner);
     39   ~LocalExtensionCache();
     40 
     41   // Name of flag file that indicates that cache is ready (import finished).
     42   static const char kCacheReadyFlagFileName[];
     43 
     44   // Initialize cache. If |wait_for_cache_initialization| is |true|, the cache
     45   // contents will not be read until a flag file appears in the cache directory,
     46   // signaling that the cache is ready. The |callback| is called when cache is
     47   // ready and cache dir content was already checked.
     48   void Init(bool wait_for_cache_initialization,
     49             const base::Closure& callback);
     50 
     51   // Shut down the cache. The |callback| will be invoked when the cache has shut
     52   // down completely and there are no more pending file I/O operations.
     53   void Shutdown(const base::Closure& callback);
     54 
     55   // If extension with |id| exists in the cache, returns |true|, |file_path| and
     56   // |version| for the extension. Extension will be marked as used with current
     57   // timestamp.
     58   bool GetExtension(const std::string& id,
     59                     base::FilePath* file_path,
     60                     std::string* version);
     61 
     62   // Put extension with |id| and |version| into local cache. Older version in
     63   // the cache will be on next run so it can be safely used. Extension will be
     64   // marked as used with current timestamp. The file will be available via
     65   // GetExtension when |callback| is called. PutExtension may get ownership
     66   // of |file_path| or return it back via |callback|.
     67   void PutExtension(const std::string& id,
     68                     const base::FilePath& file_path,
     69                     const std::string& version,
     70                     const PutExtensionCallback& callback);
     71 
     72   // Remove extension with |id| from local cache, corresponding crx file will be
     73   // removed from disk too.
     74   bool RemoveExtension(const std::string& id);
     75 
     76   // Return cache statistics. Returns |false| if cache is not ready.
     77   bool GetStatistics(uint64* cache_size,
     78                      size_t* extensions_count);
     79 
     80   bool is_ready() const { return state_ == kReady; }
     81   bool is_uninitialized() const { return state_ == kUninitialized; }
     82   bool is_shutdown() const { return state_ == kShutdown; }
     83 
     84   // For tests only!
     85   void SetCacheStatusPollingDelayForTests(const base::TimeDelta& delay);
     86 
     87  private:
     88   struct CacheItemInfo {
     89     std::string version;
     90     base::Time last_used;
     91     uint64 size;
     92     base::FilePath file_path;
     93 
     94     CacheItemInfo(const std::string& version,
     95                   const base::Time& last_used,
     96                   uint64 size,
     97                   const base::FilePath& file_path);
     98   };
     99   typedef std::map<std::string, CacheItemInfo> CacheMap;
    100 
    101   enum State {
    102     kUninitialized,
    103     kWaitInitialization,
    104     kReady,
    105     kShutdown
    106   };
    107 
    108   // Sends BackendCheckCacheStatus task on backend thread.
    109   void CheckCacheStatus(const base::Closure& callback);
    110 
    111   // Checks whether a flag file exists in the |cache_dir|, indicating that the
    112   // cache is ready. This method is invoked via the |backend_task_runner_| and
    113   // posts its result back to the |local_cache| on the UI thread.
    114   static void BackendCheckCacheStatus(
    115       base::WeakPtr<LocalExtensionCache> local_cache,
    116       const base::FilePath& cache_dir,
    117       const base::Closure& callback);
    118 
    119   // Invoked on the UI thread after checking whether the cache is ready. If the
    120   // cache is not ready yet, posts a delayed task that will repeat the check,
    121   // thus polling for cache readiness.
    122   void OnCacheStatusChecked(bool ready, const base::Closure& callback);
    123 
    124   // Checks the cache contents. This is a helper that invokes the actual check
    125   // by posting to the |backend_task_runner_|.
    126   void CheckCacheContents(const base::Closure& callback);
    127 
    128   // Checks the cache contents. This method is invoked via the
    129   // |backend_task_runner_| and posts back a list of cache entries to the
    130   // |local_cache| on the UI thread.
    131   static void BackendCheckCacheContents(
    132       base::WeakPtr<LocalExtensionCache> local_cache,
    133       const base::FilePath& cache_dir,
    134       const base::Closure& callback);
    135 
    136   // Helper for BackendCheckCacheContents() that updates |cache_content|.
    137   static void BackendCheckCacheContentsInternal(
    138       const base::FilePath& cache_dir,
    139       CacheMap* cache_content);
    140 
    141   // Invoked when the cache content on disk has been checked. |cache_content|
    142   // contains all the currently valid crx files in the cache.
    143   void OnCacheContentsChecked(scoped_ptr<CacheMap> cache_content,
    144                               const base::Closure& callback);
    145 
    146   // Update timestamp for the file to mark it as "used". This method is invoked
    147   // via the |backend_task_runner_|.
    148   static void BackendMarkFileUsed(const base::FilePath& file_path,
    149                                   const base::Time& time);
    150 
    151   // Installs the downloaded crx file at |path| in the |cache_dir|. This method
    152   // is invoked via the |backend_task_runner_|.
    153   static void BackendInstallCacheEntry(
    154       base::WeakPtr<LocalExtensionCache> local_cache,
    155       const base::FilePath& cache_dir,
    156       const std::string& id,
    157       const base::FilePath& file_path,
    158       const std::string& version,
    159       const PutExtensionCallback& callback);
    160 
    161   // Invoked on the UI thread when a new entry has been installed in the cache.
    162   void OnCacheEntryInstalled(const std::string& id,
    163                              const CacheItemInfo& info,
    164                              bool was_error,
    165                              const PutExtensionCallback& callback);
    166 
    167   // Remove cached crx files(all versions) under |cached_dir| for extension with
    168   // |id|. This method is invoked via the |backend_task_runner_|.
    169   static void BackendRemoveCacheEntry(const base::FilePath& cache_dir,
    170                                       const std::string& id);
    171 
    172   // Compare two cache items returns true if first item is older.
    173   static bool CompareCacheItemsAge(const CacheMap::iterator& lhs,
    174                                    const CacheMap::iterator& rhs);
    175 
    176   // Calculate which files need to be deleted and schedule files deletion.
    177   void CleanUp();
    178 
    179   // Path to the directory where the extension cache is stored.
    180   base::FilePath cache_dir_;
    181 
    182   // Maximum size of cache dir on disk.
    183   uint64 max_cache_size_;
    184 
    185   // Minimal age of unused item in cache, items prior to this age will be
    186   // deleted on shutdown.
    187   base::Time min_cache_age_;
    188 
    189   // Task runner for executing file I/O tasks.
    190   scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
    191 
    192   // Track state of the instance.
    193   State state_;
    194 
    195   // This contains info about all cached extensions.
    196   CacheMap cached_extensions_;
    197 
    198   // Weak factory for callbacks from the backend and delayed tasks.
    199   base::WeakPtrFactory<LocalExtensionCache> weak_ptr_factory_;
    200 
    201   // Delay between polling cache status.
    202   base::TimeDelta cache_status_polling_delay_;
    203 
    204   DISALLOW_COPY_AND_ASSIGN(LocalExtensionCache);
    205 };
    206 
    207 }  // namespace extensions
    208 
    209 #endif  // CHROME_BROWSER_EXTENSIONS_UPDATER_LOCAL_EXTENSION_CACHE_H_
    210