Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: services/url_response_disk_cache/url_response_disk_cache_impl.cc

Issue 1351693007: Add invalidation to url_response_disk_cache. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Follow review Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "services/url_response_disk_cache/url_response_disk_cache_impl.h" 5 #include "services/url_response_disk_cache/url_response_disk_cache_impl.h"
6 6
7 #include <dirent.h> 7 #include <dirent.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <sys/types.h> 9 #include <sys/types.h>
10 10
(...skipping 17 matching lines...) Expand all
28 #include "services/url_response_disk_cache/url_response_disk_cache_entry.mojom.h " 28 #include "services/url_response_disk_cache/url_response_disk_cache_entry.mojom.h "
29 #include "third_party/zlib/google/zip_reader.h" 29 #include "third_party/zlib/google/zip_reader.h"
30 #include "url/gurl.h" 30 #include "url/gurl.h"
31 31
32 namespace mojo { 32 namespace mojo {
33 33
34 namespace { 34 namespace {
35 35
36 // The current version of the cache. This should only be incremented. When this 36 // The current version of the cache. This should only be incremented. When this
37 // is incremented, all current cache entries will be invalidated. 37 // is incremented, all current cache entries will be invalidated.
38 const uint32_t kCurrentVersion = 0; 38 const uint32_t kCurrentVersion = 1;
39 39
40 // The delay to wait before starting deleting data. This is delayed to not 40 // The delay to wait before starting deleting data. This is delayed to not
41 // interfere with the shell startup. 41 // interfere with the shell startup.
42 const uint32_t kTrashDelayInSeconds = 60; 42 const uint32_t kTrashDelayInSeconds = 60;
43 43
44 // The delay between the time an entry is invalidated and the cache not
45 // returning it anymore.
46 const uint32_t kTimeUntilInvalidationInSeconds = 90;
47
44 const char kEtagHeader[] = "etag"; 48 const char kEtagHeader[] = "etag";
45 49
46 // Create a new identifier for a cache entry. This will be used as an unique 50 // Create a new identifier for a cache entry. This will be used as an unique
47 // directory name. 51 // directory name.
48 std::string GetNewIdentifier() { 52 std::string GetNewIdentifier() {
49 char bytes[32]; 53 char bytes[32];
50 crypto::RandBytes(bytes, arraysize(bytes)); 54 crypto::RandBytes(bytes, arraysize(bytes));
51 return base::HexEncode(bytes, arraysize(bytes)); 55 return base::HexEncode(bytes, arraysize(bytes));
52 } 56 }
53 57
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 GetStagingDirectory().Append(identifier); 172 GetStagingDirectory().Append(identifier);
169 base::FilePath entry_directory = GetCacheDirectory().Append(identifier); 173 base::FilePath entry_directory = GetCacheDirectory().Append(identifier);
170 base::FilePath response_body_path = entry_directory.Append(identifier); 174 base::FilePath response_body_path = entry_directory.Append(identifier);
171 base::FilePath consumer_cache_directory = 175 base::FilePath consumer_cache_directory =
172 GetConsumerCacheDirectory(entry_directory); 176 GetConsumerCacheDirectory(entry_directory);
173 177
174 CacheEntryPtr entry = CacheEntry::New(); 178 CacheEntryPtr entry = CacheEntry::New();
175 entry->response = response.Pass(); 179 entry->response = response.Pass();
176 entry->entry_directory = entry_directory.value(); 180 entry->entry_directory = entry_directory.value();
177 entry->response_body_path = response_body_path.value(); 181 entry->response_body_path = response_body_path.value();
182 entry->last_invalidation = base::Time::Max().ToInternalValue();
178 183
179 db->PutNew(request_origin, url, entry.Pass()); 184 db->PutNew(request_origin, url, entry.Pass());
180 185
181 if (!base::CreateDirectoryAndGetError(entry_directory, nullptr) || 186 if (!base::CreateDirectoryAndGetError(entry_directory, nullptr) ||
182 !base::CreateDirectoryAndGetError(consumer_cache_directory, nullptr) || 187 !base::CreateDirectoryAndGetError(consumer_cache_directory, nullptr) ||
183 !base::ReplaceFile(staged_response_body_path, response_body_path, 188 !base::ReplaceFile(staged_response_body_path, response_body_path,
184 nullptr)) { 189 nullptr)) {
185 MovePathIntoDir(entry_directory, GetStagingDirectory()); 190 MovePathIntoDir(entry_directory, GetStagingDirectory());
186 callback.Run(base::FilePath(), base::FilePath()); 191 callback.Run(base::FilePath(), base::FilePath());
187 return; 192 return;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 return false; 242 return false;
238 std::vector<std::string> response_etags = 243 std::vector<std::string> response_etags =
239 GetHeaderValues(etag_header_name, response->headers); 244 GetHeaderValues(etag_header_name, response->headers);
240 if (response_etags.size() == 0) 245 if (response_etags.size() == 0)
241 return false; 246 return false;
242 247
243 // Looking for the first etag header. 248 // Looking for the first etag header.
244 return entry_etags[0] == response_etags[0]; 249 return entry_etags[0] == response_etags[0];
245 } 250 }
246 251
252 void UpdateLastInvalidation(scoped_refptr<URLResponseDiskCacheDB> db,
253 CacheKeyPtr key,
254 const base::Time& time) {
255 CacheEntryPtr entry = db->Get(key.Clone());
256 entry->last_invalidation = time.ToInternalValue();
257 db->Put(key.Pass(), entry.Pass());
258 }
259
247 void PruneCache(scoped_refptr<URLResponseDiskCacheDB> db, 260 void PruneCache(scoped_refptr<URLResponseDiskCacheDB> db,
248 const scoped_ptr<URLResponseDiskCacheDB::Iterator>& iterator) { 261 const scoped_ptr<URLResponseDiskCacheDB::Iterator>& iterator) {
249 CacheKeyPtr last_key; 262 CacheKeyPtr last_key;
250 CacheKeyPtr key; 263 CacheKeyPtr key;
251 CacheEntryPtr entry; 264 CacheEntryPtr entry;
252 while (iterator->HasNext()) { 265 while (iterator->HasNext()) {
253 iterator->GetNext(&key, &entry); 266 iterator->GetNext(&key, &entry);
254 if (last_key && last_key->request_origin == key->request_origin && 267 if (last_key && last_key->request_origin == key->request_origin &&
255 last_key->url == key->url) { 268 last_key->url == key->url) {
256 base::FilePath entry_directory = base::FilePath(entry->entry_directory); 269 base::FilePath entry_directory = base::FilePath(entry->entry_directory);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 scoped_refptr<URLResponseDiskCacheDB> db, 323 scoped_refptr<URLResponseDiskCacheDB> db,
311 const std::string& remote_application_url, 324 const std::string& remote_application_url,
312 InterfaceRequest<URLResponseDiskCache> request) 325 InterfaceRequest<URLResponseDiskCache> request)
313 : task_runner_(task_runner), db_(db), binding_(this, request.Pass()) { 326 : task_runner_(task_runner), db_(db), binding_(this, request.Pass()) {
314 request_origin_ = GURL(remote_application_url).GetOrigin().spec(); 327 request_origin_ = GURL(remote_application_url).GetOrigin().spec();
315 } 328 }
316 329
317 URLResponseDiskCacheImpl::~URLResponseDiskCacheImpl() { 330 URLResponseDiskCacheImpl::~URLResponseDiskCacheImpl() {
318 } 331 }
319 332
333 bool IsInvalidated(const CacheEntryPtr& entry) {
334 if (!entry)
335 return true;
336 return base::Time::Now() -
337 base::Time::FromInternalValue(entry->last_invalidation) >
338 base::TimeDelta::FromSeconds(kTimeUntilInvalidationInSeconds);
339 }
340
320 void URLResponseDiskCacheImpl::Get(const String& url, 341 void URLResponseDiskCacheImpl::Get(const String& url,
321 const GetCallback& callback) { 342 const GetCallback& callback) {
322 CacheEntryPtr entry = db_->GetNewest(request_origin_, CanonicalizeURL(url)); 343 CacheKeyPtr key;
323 if (!IsCacheEntryValid(entry)) { 344 CacheEntryPtr entry =
345 db_->GetNewest(request_origin_, CanonicalizeURL(url), &key);
346 if (IsInvalidated(entry) || !IsCacheEntryValid(entry)) {
324 callback.Run(URLResponsePtr(), Array<uint8_t>(), Array<uint8_t>()); 347 callback.Run(URLResponsePtr(), Array<uint8_t>(), Array<uint8_t>());
325 return; 348 return;
326 } 349 }
327 callback.Run(entry->response.Pass(), 350 callback.Run(entry->response.Pass(),
328 PathToArray(base::FilePath(entry->response_body_path)), 351 PathToArray(base::FilePath(entry->response_body_path)),
329 PathToArray(GetConsumerCacheDirectory( 352 PathToArray(GetConsumerCacheDirectory(
330 base::FilePath(entry->entry_directory)))); 353 base::FilePath(entry->entry_directory))));
354 UpdateLastInvalidation(db_, key.Pass(), base::Time::Now());
355 }
356
357 void URLResponseDiskCacheImpl::Validate(const String& url) {
358 CacheKeyPtr key;
359 CacheEntryPtr entry =
360 db_->GetNewest(request_origin_, CanonicalizeURL(url), &key);
361 if (entry)
362 UpdateLastInvalidation(db_, key.Pass(), base::Time::Max());
331 } 363 }
332 364
333 void URLResponseDiskCacheImpl::Update(URLResponsePtr response) { 365 void URLResponseDiskCacheImpl::Update(URLResponsePtr response) {
334 UpdateAndGetInternal(response.Pass(), base::Bind(&DoNothing)); 366 UpdateAndGetInternal(response.Pass(), base::Bind(&DoNothing));
335 } 367 }
336 368
337 void URLResponseDiskCacheImpl::UpdateAndGet( 369 void URLResponseDiskCacheImpl::UpdateAndGet(
338 URLResponsePtr response, 370 URLResponsePtr response,
339 const UpdateAndGetCallback& callback) { 371 const UpdateAndGetCallback& callback) {
340 UpdateAndGetInternal(response.Pass(), base::Bind(&RunMojoCallback, callback)); 372 UpdateAndGetInternal(response.Pass(), base::Bind(&RunMojoCallback, callback));
341 } 373 }
342 374
343 void URLResponseDiskCacheImpl::UpdateAndGetExtracted( 375 void URLResponseDiskCacheImpl::UpdateAndGetExtracted(
344 URLResponsePtr response, 376 URLResponsePtr response,
345 const UpdateAndGetExtractedCallback& callback) { 377 const UpdateAndGetExtractedCallback& callback) {
346 if (response->error || 378 UpdateAndGetInternal(
347 (response->status_code >= 400 && response->status_code < 600)) { 379 response.Pass(),
348 callback.Run(Array<uint8_t>(), Array<uint8_t>()); 380 base::Bind(&URLResponseDiskCacheImpl::UpdateAndGetExtractedInternal,
349 return; 381 base::Unretained(this),
350 } 382 base::Bind(&RunMojoCallback, callback)));
351
352 std::string url = CanonicalizeURL(response->url);
353
354 // Check if the response is cached and valid. If that's the case, returns the
355 // cached value.
356 CacheEntryPtr entry = db_->GetNewest(request_origin_, url);
357
358 if (!IsCacheEntryFresh(response, entry)) {
359 UpdateAndGetInternal(
360 response.Pass(),
361 base::Bind(&URLResponseDiskCacheImpl::UpdateAndGetExtractedInternal,
362 base::Unretained(this),
363 base::Bind(&RunMojoCallback, callback)));
364 return;
365 }
366
367 base::FilePath entry_directory = base::FilePath(entry->entry_directory);
368 base::FilePath extraction_directory = GetExtractionDirectory(entry_directory);
369 if (!PathExists(GetExtractionSentinel(entry_directory))) {
370 UpdateAndGetExtractedInternal(base::Bind(&RunMojoCallback, callback),
371 base::FilePath(entry->response_body_path),
372 GetConsumerCacheDirectory(entry_directory));
373 return;
374 }
375
376 callback.Run(PathToArray(extraction_directory),
377 PathToArray(GetConsumerCacheDirectory(entry_directory)));
378 } 383 }
379 384
380 void URLResponseDiskCacheImpl::UpdateAndGetInternal( 385 void URLResponseDiskCacheImpl::UpdateAndGetInternal(
381 URLResponsePtr response, 386 URLResponsePtr response,
382 const ResponseFileAndCacheDirCallback& callback) { 387 const ResponseFileAndCacheDirCallback& callback) {
383 if (response->error || 388 if (response->error ||
384 (response->status_code >= 400 && response->status_code < 600)) { 389 (response->status_code >= 400 && response->status_code < 600)) {
385 callback.Run(base::FilePath(), base::FilePath()); 390 callback.Run(base::FilePath(), base::FilePath());
386 return; 391 return;
387 } 392 }
388 393
389 std::string url = CanonicalizeURL(response->url); 394 std::string url = CanonicalizeURL(response->url);
390 395
391 // Check if the response is cached and valid. If that's the case, returns 396 // Check if the response is cached and valid. If that's the case, returns
392 // the cached value. 397 // the cached value.
393 CacheEntryPtr entry = db_->GetNewest(request_origin_, url); 398 CacheKeyPtr key;
399 CacheEntryPtr entry = db_->GetNewest(request_origin_, url, &key);
394 if (IsCacheEntryFresh(response, entry)) { 400 if (IsCacheEntryFresh(response, entry)) {
395 callback.Run( 401 callback.Run(
396 base::FilePath(entry->response_body_path), 402 base::FilePath(entry->response_body_path),
397 GetConsumerCacheDirectory(base::FilePath(entry->entry_directory))); 403 GetConsumerCacheDirectory(base::FilePath(entry->entry_directory)));
404 UpdateLastInvalidation(db_, key.Pass(), base::Time::Max());
398 return; 405 return;
399 } 406 }
400 407
401 if (!response->body.is_valid()) { 408 if (!response->body.is_valid()) {
402 callback.Run(base::FilePath(), base::FilePath()); 409 callback.Run(base::FilePath(), base::FilePath());
403 return; 410 return;
404 } 411 }
405 412
406 std::string identifier = GetNewIdentifier(); 413 std::string identifier = GetNewIdentifier();
407 // The content is copied to the staging directory so that files are not leaked 414 // The content is copied to the staging directory so that files are not leaked
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 return; 472 return;
466 } 473 }
467 } 474 }
468 // We can ignore write error, as it will just force to clear the cache on the 475 // We can ignore write error, as it will just force to clear the cache on the
469 // next request. 476 // next request.
470 WriteFile(GetExtractionSentinel(entry_directory), nullptr, 0); 477 WriteFile(GetExtractionSentinel(entry_directory), nullptr, 0);
471 callback.Run(extraction_directory, consumer_cache_directory); 478 callback.Run(extraction_directory, consumer_cache_directory);
472 } 479 }
473 480
474 } // namespace mojo 481 } // namespace mojo
OLDNEW
« no previous file with comments | « services/url_response_disk_cache/url_response_disk_cache_impl.h ('k') | shell/application_manager/network_fetcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698