• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
is_ready()80   bool is_ready() const { return state_ == kReady; }
is_uninitialized()81   bool is_uninitialized() const { return state_ == kUninitialized; }
is_shutdown()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