Index: content/browser/appcache/chrome_appcache_service.cc |
diff --git a/content/browser/appcache/chrome_appcache_service.cc b/content/browser/appcache/chrome_appcache_service.cc |
index dd593efdea1343aa50d5ad7b691f8e30195ca85a..09348dbad37475fbdb349bbe98b6731f6455f573 100644 |
--- a/content/browser/appcache/chrome_appcache_service.cc |
+++ b/content/browser/appcache/chrome_appcache_service.cc |
@@ -9,38 +9,32 @@ |
#include "content/browser/content_browser_client.h" |
#include "content/common/notification_service.h" |
#include "net/base/net_errors.h" |
+#include "webkit/appcache/appcache_interfaces.h" |
#include "webkit/appcache/appcache_thread.h" |
#include "webkit/quota/quota_manager.h" |
static bool has_initialized_thread_ids; |
-namespace { |
- |
-// Used to defer deleting of local storage until the destructor has finished. |
-void DeleteLocalStateOnIOThread(FilePath cache_path) { |
- // Post the actual deletion to the DB thread to ensure it happens after the |
- // database file has been closed. |
- BrowserThread::PostTask( |
- BrowserThread::DB, FROM_HERE, |
- NewRunnableFunction<bool(*)(const FilePath&, bool), FilePath, bool>( |
- &file_util::Delete, cache_path, true)); |
-} |
- |
-} // namespace |
- |
// ---------------------------------------------------------------------------- |
ChromeAppCacheService::ChromeAppCacheService( |
quota::QuotaManagerProxy* quota_manager_proxy) |
: AppCacheService(quota_manager_proxy), |
- resource_context_(NULL), clear_local_state_on_exit_(false) { |
+ resource_context_(NULL), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(appcache_got_info_callback_( |
+ this, &ChromeAppCacheService::OnGotAppCacheInfo)), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(appcache_deleted_callback_( |
+ this, &ChromeAppCacheService::OnAppCacheDeleted)), |
+ appcaches_to_be_deleted_count_(0), |
+ appcaches_cleared_event_(new base::WaitableEvent(true, false)), |
+ appcaches_cleared_callback_(NULL), |
+ waiting_for_clear_appcaches_(false) { |
} |
void ChromeAppCacheService::InitializeOnIOThread( |
const FilePath& cache_path, |
const content::ResourceContext* resource_context, |
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy, |
- bool clear_local_state_on_exit) { |
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
if (!has_initialized_thread_ids) { |
@@ -53,7 +47,6 @@ void ChromeAppCacheService::InitializeOnIOThread( |
registrar_.Add( |
this, content::NOTIFICATION_PURGE_MEMORY, |
NotificationService::AllSources()); |
- SetClearLocalStateOnExit(clear_local_state_on_exit); |
// Init our base class. |
Initialize(cache_path_, |
@@ -63,26 +56,68 @@ void ChromeAppCacheService::InitializeOnIOThread( |
} |
ChromeAppCacheService::~ChromeAppCacheService() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+} |
- if (clear_local_state_on_exit_ && !cache_path_.empty()) { |
+base::WaitableEvent* ChromeAppCacheService::ClearAppCache( |
+ net::CompletionCallback* callback) |
+{ |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, |
- NewRunnableFunction(DeleteLocalStateOnIOThread, cache_path_)); |
+ NewRunnableMethod(this, |
+ &ChromeAppCacheService::ClearAppCache, |
+ callback)); |
+ return appcaches_cleared_event_.get(); |
} |
+ // Only one appcache deletion (async or sync) should be in progress at any |
+ // given time. |
+ DCHECK(waiting_for_clear_appcaches_ == false); |
+ waiting_for_clear_appcaches_ = true; |
+ appcaches_cleared_callback_ = callback; |
+ appcaches_cleared_event_->Reset(); |
+ |
+ // Keep the ChromeAppCacheService instance alive until the deletion has |
+ // finished. |
+ AddRef(); |
+ |
+ appcache_info_ = new appcache::AppCacheInfoCollection; |
+ GetAllAppCacheInfo( |
+ appcache_info_, &appcache_got_info_callback_); |
+ // Continues in OnGotAppCacheInfo. |
+ |
+ return appcaches_cleared_event_.get(); |
} |
-void ChromeAppCacheService::SetClearLocalStateOnExit(bool clear_local_state) { |
- // TODO(michaeln): How is 'protected' status granted to apps in this case? |
+void ChromeAppCacheService::SyncClearAppCacheOnIOThread() { |
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, |
NewRunnableMethod(this, |
- &ChromeAppCacheService::SetClearLocalStateOnExit, |
- clear_local_state)); |
+ &ChromeAppCacheService::SyncClearAppCacheOnIOThread)); |
return; |
} |
- clear_local_state_on_exit_ = clear_local_state; |
+ |
+ // Only one appcache deletion (async or sync) should be in progress at any |
+ // given time. |
+ DCHECK(waiting_for_clear_appcaches_ == false); |
+ waiting_for_clear_appcaches_ = true; |
+ |
+ appcache_info_ = new appcache::AppCacheInfoCollection; |
+ SyncGetAllAppCacheInfo(appcache_info_); |
+ |
+ typedef std::map<GURL, appcache::AppCacheInfoVector> InfoByOrigin; |
+ for (InfoByOrigin::const_iterator origin = |
+ appcache_info_->infos_by_origin.begin(); |
+ origin != appcache_info_->infos_by_origin.end(); ++origin) { |
+ if (special_storage_policy_->IsStorageProtected(origin->first)) |
+ continue; |
+ appcache::AppCacheInfoVector::const_iterator info; |
+ for (info = origin->second.begin(); info != origin->second.end(); ++info) { |
+ SyncDeleteAppCacheGroup(info->manifest_url); |
+ } |
+ } |
+ waiting_for_clear_appcaches_ = false; |
+ appcache_info_ = NULL; |
} |
bool ChromeAppCacheService::CanLoadAppCache(const GURL& manifest_url) { |
@@ -107,6 +142,44 @@ void ChromeAppCacheService::Observe(int type, |
PurgeMemory(); |
} |
+void ChromeAppCacheService::OnGotAppCacheInfo(int rv) { |
+ typedef std::map<GURL, appcache::AppCacheInfoVector> InfoByOrigin; |
+ |
+ appcaches_to_be_deleted_count_ = 0; |
+ for (InfoByOrigin::const_iterator origin = |
+ appcache_info_->infos_by_origin.begin(); |
+ origin != appcache_info_->infos_by_origin.end(); ++origin) { |
+ |
+ if (special_storage_policy_->IsStorageProtected(origin->first)) |
+ continue; |
+ |
+ appcache::AppCacheInfoVector::const_iterator info; |
+ for (info = origin->second.begin(); info != origin->second.end(); ++info) { |
+ ++appcaches_to_be_deleted_count_; |
+ DeleteAppCacheGroup(info->manifest_url, &appcache_deleted_callback_); |
+ } |
+ } |
+ |
+ if (appcaches_to_be_deleted_count_ == 0) |
+ OnClearedAppCache(); |
+ // Else continues in OnAppCacheDeleted. |
+} |
+ |
+void ChromeAppCacheService::OnAppCacheDeleted(int rv) { |
+ --appcaches_to_be_deleted_count_; |
+ if (appcaches_to_be_deleted_count_ == 0) |
+ OnClearedAppCache(); |
+} |
+ |
+void ChromeAppCacheService::OnClearedAppCache() { |
+ appcaches_cleared_event_->Signal(); |
+ if (appcaches_cleared_callback_) { |
+ appcaches_cleared_callback_->Run(0); |
+ } |
+ waiting_for_clear_appcaches_ = false; |
+ Release(); |
+} |
+ |
// ---------------------------------------------------------------------------- |
static BrowserThread::ID ToBrowserThreadID(int id) { |