Rename GetIconID to GetIconId
[chromium-blink-merge.git] / chrome / browser / extensions / updater / local_extension_cache.h
blobffb38c270ea99e9fa24f63bb0654b2d81908ed69
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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_UPDATER_LOCAL_EXTENSION_CACHE_H_
6 #define CHROME_BROWSER_EXTENSIONS_UPDATER_LOCAL_EXTENSION_CACHE_H_
8 #include <map>
9 #include <string>
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"
17 namespace extensions {
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;
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();
41 // Name of flag file that indicates that cache is ready (import finished).
42 static const char kCacheReadyFlagFileName[];
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);
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);
55 // If extension with |id| and |expected_hash| exists in the cache (or there
56 // is an extension with the same |id|, but without expected hash sum),
57 // returns |true|, |file_path| and |version| for the found extension.
58 // If |file_path| was requested, then extension will be marked as used with
59 // current timestamp.
60 bool GetExtension(const std::string& id,
61 const std::string& expected_hash,
62 base::FilePath* file_path,
63 std::string* version);
65 // Returns |true| if there is a file with |id| and |expected_hash| in the
66 // cache, and its hash sum is actually empty. After removing it from cache and
67 // re-downloading, the new entry will have some non-empty hash sum.
68 bool ShouldRetryDownload(const std::string& id,
69 const std::string& expected_hash);
71 // Put extension with |id|, |version| and |expected_hash| into local cache.
72 // Older version in the cache will be deleted on next run so it can be safely
73 // used. Extension will be marked as used with current timestamp. The file
74 // will be available via GetExtension when |callback| is called. PutExtension
75 // may get ownership of |file_path| or return it back via |callback|.
76 void PutExtension(const std::string& id,
77 const std::string& expected_hash,
78 const base::FilePath& file_path,
79 const std::string& version,
80 const PutExtensionCallback& callback);
82 // Remove extension with |id| and |expected_hash| from local cache,
83 // corresponding crx file will be removed from disk too. If |expected_hash| is
84 // empty, all files corresponding to that |id| will be removed.
85 bool RemoveExtension(const std::string& id, const std::string& expected_hash);
87 // Return cache statistics. Returns |false| if cache is not ready.
88 bool GetStatistics(uint64* cache_size,
89 size_t* extensions_count);
91 // Outputs properly formatted extension file name, as it will be stored in
92 // cache. If |expected_hash| is empty, it will be <id>-<version>.crx,
93 // otherwise the name format is <id>-<version>-<hash>.crx.
94 static std::string ExtensionFileName(const std::string& id,
95 const std::string& version,
96 const std::string& expected_hash);
98 bool is_ready() const { return state_ == kReady; }
99 bool is_uninitialized() const { return state_ == kUninitialized; }
100 bool is_shutdown() const { return state_ == kShutdown; }
102 // For tests only!
103 void SetCacheStatusPollingDelayForTests(const base::TimeDelta& delay);
105 private:
106 struct CacheItemInfo {
107 std::string version;
108 std::string expected_hash;
109 base::Time last_used;
110 uint64 size;
111 base::FilePath file_path;
113 CacheItemInfo(const std::string& version,
114 const std::string& expected_hash,
115 const base::Time& last_used,
116 uint64 size,
117 const base::FilePath& file_path);
118 ~CacheItemInfo();
120 typedef std::multimap<std::string, CacheItemInfo> CacheMap;
121 typedef std::pair<CacheMap::iterator, CacheMap::iterator> CacheHit;
123 enum State {
124 kUninitialized,
125 kWaitInitialization,
126 kReady,
127 kShutdown
130 // Helper function that searches the cache map for an extension with the
131 // specified |id| and |expected_hash|. If there is an extension with empty
132 // hash in the map, it will be returned. If |expected_hash| is empty, returns
133 // the first extension with the same |id|.
134 static CacheMap::iterator FindExtension(CacheMap& cache,
135 const std::string& id,
136 const std::string& expected_hash);
138 // Helper function that compares a cache entry (typically returned from
139 // FindExtension) with an incoming |version| and |expected_hash|. Comparison
140 // is based on the version number (newer is better) and hash sum (it is
141 // better to have a file with an expected hash sum than without it).
142 // Return value of this function is |true| if we already have a 'better'
143 // entry in cache (considering both version number and hash sum), and the
144 // value of |compare| is set to the version number comparison result (as
145 // returned by Version::CompareTo).
146 static bool NewerOrSame(const CacheMap::iterator& entry,
147 const std::string& version,
148 const std::string& expected_hash,
149 int* compare);
151 // Helper function that checks if there is already a newer version of the
152 // extension we want to add to the cache, or if there is already a file with a
153 // hash sum (and we are trying to add one without it), or vice versa. Keeps
154 // the invariant of having only one version of each extension, and either only
155 // unhashed (single) or only hashed (multiple) variants of that version.
156 // |delete_files| specifies if this function is called on startup (in which
157 // case we will clean up files we don't need), or on extension install.
158 // Returns cache.end() if the extension is already cached, or an iterator to
159 // the inserted cache entry otherwise.
160 static CacheMap::iterator InsertCacheEntry(CacheMap& cache,
161 const std::string& id,
162 const CacheItemInfo& info,
163 const bool delete_files);
165 // Remove extension at a specified iterator. This is necessary because
166 // removing an extension by |id| and |expected_hash| taken by reference from
167 // an iterator leads to use-after-free. On the other hand, when passing the
168 // iterator itself we avoid lookup as such, at all.
169 // For external calls from RemoveExtension without expected hash we will
170 // ignore the hash in iterator by setting |match_hash| to false.
171 bool RemoveExtensionAt(const CacheMap::iterator& it, bool match_hash);
173 // Sends BackendCheckCacheStatus task on backend thread.
174 void CheckCacheStatus(const base::Closure& callback);
176 // Checks whether a flag file exists in the |cache_dir|, indicating that the
177 // cache is ready. This method is invoked via the |backend_task_runner_| and
178 // posts its result back to the |local_cache| on the UI thread.
179 static void BackendCheckCacheStatus(
180 base::WeakPtr<LocalExtensionCache> local_cache,
181 const base::FilePath& cache_dir,
182 const base::Closure& callback);
184 // Invoked on the UI thread after checking whether the cache is ready. If the
185 // cache is not ready yet, posts a delayed task that will repeat the check,
186 // thus polling for cache readiness.
187 void OnCacheStatusChecked(bool ready, const base::Closure& callback);
189 // Checks the cache contents. This is a helper that invokes the actual check
190 // by posting to the |backend_task_runner_|.
191 void CheckCacheContents(const base::Closure& callback);
193 // Checks the cache contents. This method is invoked via the
194 // |backend_task_runner_| and posts back a list of cache entries to the
195 // |local_cache| on the UI thread.
196 static void BackendCheckCacheContents(
197 base::WeakPtr<LocalExtensionCache> local_cache,
198 const base::FilePath& cache_dir,
199 const base::Closure& callback);
201 // Helper for BackendCheckCacheContents() that updates |cache_content|.
202 static void BackendCheckCacheContentsInternal(
203 const base::FilePath& cache_dir,
204 CacheMap* cache_content);
206 // Invoked when the cache content on disk has been checked. |cache_content|
207 // contains all the currently valid crx files in the cache.
208 void OnCacheContentsChecked(scoped_ptr<CacheMap> cache_content,
209 const base::Closure& callback);
211 // Update timestamp for the file to mark it as "used". This method is invoked
212 // via the |backend_task_runner_|.
213 static void BackendMarkFileUsed(const base::FilePath& file_path,
214 const base::Time& time);
216 // Installs the downloaded crx file at |path| in the |cache_dir|. This method
217 // is invoked via the |backend_task_runner_|.
218 static void BackendInstallCacheEntry(
219 base::WeakPtr<LocalExtensionCache> local_cache,
220 const base::FilePath& cache_dir,
221 const std::string& id,
222 const std::string& expected_hash,
223 const base::FilePath& file_path,
224 const std::string& version,
225 const PutExtensionCallback& callback);
227 // Invoked on the UI thread when a new entry has been installed in the cache.
228 void OnCacheEntryInstalled(const std::string& id,
229 const CacheItemInfo& info,
230 bool was_error,
231 const PutExtensionCallback& callback);
233 // Remove cached crx files(all versions) under |cached_dir| for extension with
234 // |id|. This method is invoked via the |backend_task_runner_|.
235 static void BackendRemoveCacheEntry(const base::FilePath& cache_dir,
236 const std::string& expected_hash,
237 const std::string& id);
239 // Compare two cache items returns true if first item is older.
240 static bool CompareCacheItemsAge(const CacheMap::iterator& lhs,
241 const CacheMap::iterator& rhs);
243 // Calculate which files need to be deleted and schedule files deletion.
244 void CleanUp();
246 // Path to the directory where the extension cache is stored.
247 base::FilePath cache_dir_;
249 // Maximum size of cache dir on disk.
250 uint64 max_cache_size_;
252 // Minimal age of unused item in cache, items prior to this age will be
253 // deleted on shutdown.
254 base::Time min_cache_age_;
256 // Task runner for executing file I/O tasks.
257 scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
259 // Track state of the instance.
260 State state_;
262 // This contains info about all cached extensions.
263 CacheMap cached_extensions_;
265 // Delay between polling cache status.
266 base::TimeDelta cache_status_polling_delay_;
268 // Weak factory for callbacks from the backend and delayed tasks.
269 base::WeakPtrFactory<LocalExtensionCache> weak_ptr_factory_;
271 DISALLOW_COPY_AND_ASSIGN(LocalExtensionCache);
274 } // namespace extensions
276 #endif // CHROME_BROWSER_EXTENSIONS_UPDATER_LOCAL_EXTENSION_CACHE_H_