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