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