summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browsing_data_appcache_helper.cc96
-rw-r--r--chrome/browser/browsing_data_appcache_helper.h39
-rw-r--r--chrome/browser/browsing_data_remover.cc86
-rw-r--r--chrome/browser/browsing_data_remover.h30
-rw-r--r--chrome/browser/cookies_tree_model.cc29
-rw-r--r--chrome/browser/cookies_tree_model.h11
-rw-r--r--chrome/browser/gtk/gtk_chrome_cookie_view.cc2
-rw-r--r--chrome/browser/gtk/gtk_chrome_cookie_view.h2
-rw-r--r--chrome/browser/mock_browsing_data_appcache_helper.cc3
-rw-r--r--chrome/browser/mock_browsing_data_appcache_helper.h2
-rwxr-xr-xchrome/browser/views/appcache_info_view.cc3
-rwxr-xr-xchrome/browser/views/appcache_info_view.h2
-rw-r--r--webkit/appcache/appcache_group.cc17
-rw-r--r--webkit/appcache/appcache_group.h7
-rw-r--r--webkit/appcache/appcache_host.cc14
-rw-r--r--webkit/appcache/appcache_service.cc138
-rw-r--r--webkit/appcache/appcache_service.h64
-rw-r--r--webkit/appcache/appcache_storage.h9
-rw-r--r--webkit/appcache/appcache_storage_impl.cc61
-rw-r--r--webkit/appcache/appcache_storage_impl.h4
-rw-r--r--webkit/appcache/mock_appcache_storage.h1
21 files changed, 509 insertions, 111 deletions
diff --git a/chrome/browser/browsing_data_appcache_helper.cc b/chrome/browser/browsing_data_appcache_helper.cc
index c0d7ced..9e62809 100644
--- a/chrome/browser/browsing_data_appcache_helper.cc
+++ b/chrome/browser/browsing_data_appcache_helper.cc
@@ -3,55 +3,70 @@
// found in the LICENSE file.
#include "chrome/browser/browsing_data_appcache_helper.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/profile.h"
+#include "webkit/appcache/appcache_database.h"
+#include "webkit/appcache/appcache_storage.h"
+
+using appcache::AppCacheDatabase;
BrowsingDataAppCacheHelper::BrowsingDataAppCacheHelper(Profile* profile)
- : is_fetching_(false) {
+ : request_context_getter_(profile->GetRequestContext()),
+ is_fetching_(false) {
+ DCHECK(request_context_getter_.get());
}
void BrowsingDataAppCacheHelper::StartFetching(Callback0::Type* callback) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- DCHECK(!is_fetching_);
- DCHECK(callback);
- is_fetching_ = true;
- info_list_.clear();
- completion_callback_.reset(callback);
- ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, NewRunnableMethod(
- this, &BrowsingDataAppCacheHelper::StartFetchingInIOThread));
+ if (ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ DCHECK(!is_fetching_);
+ DCHECK(callback);
+ is_fetching_ = true;
+ info_collection_ = new appcache::AppCacheInfoCollection;
+ completion_callback_.reset(callback);
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, NewRunnableMethod(
+ this, &BrowsingDataAppCacheHelper::StartFetching, callback));
+ return;
+ }
+
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ appcache_info_callback_ =
+ new net::CancelableCompletionCallback<BrowsingDataAppCacheHelper>(
+ this, &BrowsingDataAppCacheHelper::OnFetchComplete);
+ GetAppCacheService()->GetAllAppCacheInfo(info_collection_,
+ appcache_info_callback_);
}
void BrowsingDataAppCacheHelper::CancelNotification() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- completion_callback_.reset();
-}
+ if (ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ completion_callback_.reset();
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, NewRunnableMethod(
+ this, &BrowsingDataAppCacheHelper::CancelNotification));
+ return;
+ }
-void BrowsingDataAppCacheHelper::DeleteAppCache(int64 group_id) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, NewRunnableMethod(
- this, &BrowsingDataAppCacheHelper::DeleteAppCacheInIOThread,
- group_id));
+ if (appcache_info_callback_)
+ appcache_info_callback_.release()->Cancel();
}
-void BrowsingDataAppCacheHelper::StartFetchingInIOThread() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-
-#ifndef NDEBUG
- // TODO(michaeln): get real data from the appcache service
- info_list_.push_back(
- AppCacheInfo(GURL("http://bogus/manifest"),
- 1 * 1024 * 1024, base::Time::Now(), base::Time::Now(), 1));
- info_list_.push_back(
- AppCacheInfo(GURL("https://bogus/manifest"),
- 2 * 1024 * 1024, base::Time::Now(), base::Time::Now(), 2));
- info_list_.push_back(
- AppCacheInfo(GURL("http://bogus:8080/manifest"),
- 3 * 1024 * 1024, base::Time::Now(), base::Time::Now(), 3));
-#endif
-
- ChromeThread::PostTask(ChromeThread::UI, FROM_HERE, NewRunnableMethod(
- this, &BrowsingDataAppCacheHelper::OnFetchComplete));
+void BrowsingDataAppCacheHelper::DeleteAppCacheGroup(
+ const GURL& manifest_url) {
+ if (ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, NewRunnableMethod(
+ this, &BrowsingDataAppCacheHelper::DeleteAppCacheGroup,
+ manifest_url));
+ return;
+ }
+ GetAppCacheService()->DeleteAppCacheGroup(manifest_url, NULL);
}
-void BrowsingDataAppCacheHelper::OnFetchComplete() {
+void BrowsingDataAppCacheHelper::OnFetchComplete(int rv) {
+ if (ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ appcache_info_callback_ = NULL;
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE, NewRunnableMethod(
+ this, &BrowsingDataAppCacheHelper::OnFetchComplete, rv));
+ return;
+ }
+
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
DCHECK(is_fetching_);
is_fetching_ = false;
@@ -61,8 +76,11 @@ void BrowsingDataAppCacheHelper::OnFetchComplete() {
}
}
-void BrowsingDataAppCacheHelper::DeleteAppCacheInIOThread(
- int64 group_id) {
+ChromeAppCacheService* BrowsingDataAppCacheHelper::GetAppCacheService() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- // TODO(michaeln): plumb to the appcache service
+ ChromeURLRequestContext* request_context =
+ reinterpret_cast<ChromeURLRequestContext*>(
+ request_context_getter_->GetURLRequestContext());
+ return request_context ? request_context->appcache_service()
+ : NULL;
}
diff --git a/chrome/browser/browsing_data_appcache_helper.h b/chrome/browser/browsing_data_appcache_helper.h
index aa04dae..695a271 100644
--- a/chrome/browser/browsing_data_appcache_helper.h
+++ b/chrome/browser/browsing_data_appcache_helper.h
@@ -11,6 +11,7 @@
#include "base/scoped_ptr.h"
#include "base/task.h"
#include "chrome/browser/appcache/chrome_appcache_service.h"
+#include "chrome/browser/net/url_request_context_getter.h"
class Profile;
@@ -19,37 +20,15 @@ class Profile;
class BrowsingDataAppCacheHelper
: public base::RefCountedThreadSafe<BrowsingDataAppCacheHelper> {
public:
- // Contains detailed information about an appcache.
- struct AppCacheInfo {
- AppCacheInfo() {}
- AppCacheInfo(const GURL& manifest_url,
- int64 size,
- base::Time creation_time,
- base::Time last_access_time,
- int64 group_id)
- : manifest_url(manifest_url),
- size(size),
- creation_time(creation_time),
- last_access_time(last_access_time),
- group_id(group_id) {
- }
-
- GURL manifest_url;
- int64 size;
- base::Time creation_time;
- base::Time last_access_time;
- int64 group_id;
- };
-
explicit BrowsingDataAppCacheHelper(Profile* profile);
virtual void StartFetching(Callback0::Type* completion_callback);
virtual void CancelNotification();
- virtual void DeleteAppCache(int64 group_id);
+ virtual void DeleteAppCacheGroup(const GURL& manifest_url);
- const std::vector<AppCacheInfo>& info_list() const {
+ appcache::AppCacheInfoCollection* info_collection() const {
DCHECK(!is_fetching_);
- return info_list_;
+ return info_collection_;
}
private:
@@ -58,13 +37,15 @@ class BrowsingDataAppCacheHelper
virtual ~BrowsingDataAppCacheHelper() {}
- void StartFetchingInIOThread();
- void OnFetchComplete();
- void DeleteAppCacheInIOThread(int64 group_id);
+ void OnFetchComplete(int rv);
+ ChromeAppCacheService* GetAppCacheService();
+ scoped_refptr<URLRequestContextGetter> request_context_getter_;
bool is_fetching_;
- std::vector<AppCacheInfo> info_list_;
scoped_ptr<Callback0::Type> completion_callback_;
+ scoped_refptr<appcache::AppCacheInfoCollection> info_collection_;
+ scoped_refptr<net::CancelableCompletionCallback<BrowsingDataAppCacheHelper> >
+ appcache_info_callback_;
DISALLOW_COPY_AND_ASSIGN(BrowsingDataAppCacheHelper);
};
diff --git a/chrome/browser/browsing_data_remover.cc b/chrome/browser/browsing_data_remover.cc
index b4468c7..0614969 100644
--- a/chrome/browser/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data_remover.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/browser/password_manager/password_store.h"
#include "chrome/browser/search_engines/template_url_model.h"
@@ -46,9 +47,16 @@ BrowsingDataRemover::BrowsingDataRemover(Profile* profile,
delete_end_(delete_end),
ALLOW_THIS_IN_INITIALIZER_LIST(database_cleared_callback_(
this, &BrowsingDataRemover::OnClearedDatabases)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(appcache_got_info_callback_(
+ this, &BrowsingDataRemover::OnGotAppCacheInfo)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(appcache_deleted_callback_(
+ this, &BrowsingDataRemover::OnAppCacheDeleted)),
+ request_context_getter_(profile->GetRequestContext()),
+ appcaches_to_be_deleted_count_(0),
waiting_for_clear_databases_(false),
waiting_for_clear_history_(false),
- waiting_for_clear_cache_(false) {
+ waiting_for_clear_cache_(false),
+ waiting_for_clear_appcache_(false) {
DCHECK(profile);
}
@@ -60,9 +68,16 @@ BrowsingDataRemover::BrowsingDataRemover(Profile* profile,
delete_end_(delete_end),
ALLOW_THIS_IN_INITIALIZER_LIST(database_cleared_callback_(
this, &BrowsingDataRemover::OnClearedDatabases)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(appcache_got_info_callback_(
+ this, &BrowsingDataRemover::OnGotAppCacheInfo)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(appcache_deleted_callback_(
+ this, &BrowsingDataRemover::OnAppCacheDeleted)),
+ request_context_getter_(profile->GetRequestContext()),
+ appcaches_to_be_deleted_count_(0),
waiting_for_clear_databases_(false),
waiting_for_clear_history_(false),
- waiting_for_clear_cache_(false) {
+ waiting_for_clear_cache_(false),
+ waiting_for_clear_appcache_(false) {
DCHECK(profile);
}
@@ -146,7 +161,13 @@ void BrowsingDataRemover::Remove(int remove_mask) {
profile_->GetTransportSecurityState();
ts_state->DeleteSince(delete_begin_);
- // TODO(michaeln): clear appcaches created in the date range
+ waiting_for_clear_appcache_ = true;
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &BrowsingDataRemover::ClearAppCacheOnIOThread,
+ delete_begin_)); // we assume end time == now
}
if (remove_mask & REMOVE_PASSWORDS) {
@@ -336,3 +357,62 @@ void BrowsingDataRemover::ClearDatabasesOnFILEThread(base::Time delete_begin) {
if (rv != net::ERR_IO_PENDING)
OnClearedDatabases(rv);
}
+
+void BrowsingDataRemover::OnClearedAppCache() {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ bool result = ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &BrowsingDataRemover::OnClearedAppCache));
+ DCHECK(result);
+ return;
+ }
+ waiting_for_clear_appcache_ = false;
+ NotifyAndDeleteIfDone();
+}
+
+void BrowsingDataRemover::ClearAppCacheOnIOThread(base::Time delete_begin) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ DCHECK(waiting_for_clear_appcache_);
+
+ appcache_info_ = new appcache::AppCacheInfoCollection;
+ GetAppCacheService()->GetAllAppCacheInfo(
+ appcache_info_, &appcache_got_info_callback_);
+ // continues in OnGotAppCacheInfo
+}
+
+void BrowsingDataRemover::OnGotAppCacheInfo(int rv) {
+ using appcache::AppCacheInfoVector;
+ typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin;
+
+ for (InfoByOrigin::const_iterator origin =
+ appcache_info_->infos_by_origin.begin();
+ origin != appcache_info_->infos_by_origin.end(); ++origin) {
+ for (AppCacheInfoVector::const_iterator info = origin->second.begin();
+ info != origin->second.end(); ++info) {
+ if (info->creation_time > delete_begin_) {
+ ++appcaches_to_be_deleted_count_;
+ GetAppCacheService()->DeleteAppCacheGroup(
+ info->manifest_url, &appcache_deleted_callback_);
+ }
+ }
+ }
+
+ if (!appcaches_to_be_deleted_count_)
+ OnClearedAppCache();
+ // else continues in OnAppCacheDeleted
+}
+
+void BrowsingDataRemover::OnAppCacheDeleted(int rv) {
+ --appcaches_to_be_deleted_count_;
+ if (!appcaches_to_be_deleted_count_)
+ OnClearedAppCache();
+}
+
+ChromeAppCacheService* BrowsingDataRemover::GetAppCacheService() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ ChromeURLRequestContext* request_context =
+ reinterpret_cast<ChromeURLRequestContext*>(
+ request_context_getter_->GetURLRequestContext());
+ return request_context ? request_context->appcache_service()
+ : NULL;
+}
diff --git a/chrome/browser/browsing_data_remover.h b/chrome/browser/browsing_data_remover.h
index 74ba60e..591427c 100644
--- a/chrome/browser/browsing_data_remover.h
+++ b/chrome/browser/browsing_data_remover.h
@@ -8,6 +8,7 @@
#include "base/observer_list.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
+#include "chrome/browser/appcache/chrome_appcache_service.h"
#include "chrome/browser/cancelable_request.h"
#include "chrome/common/notification_registrar.h"
#include "webkit/database/database_tracker.h"
@@ -104,13 +105,26 @@ class BrowsingDataRemover : public NotificationObserver {
// Invoked on the FILE thread to delete HTML5 databases.
void ClearDatabasesOnFILEThread(base::Time delete_begin);
+ // Callback when the appcache has been cleared. Invokes
+ // NotifyAndDeleteIfDone.
+ void OnClearedAppCache();
+
+ // Invoked on the IO thread to delete from the AppCache.
+ void ClearAppCacheOnIOThread(base::Time delete_begin);
+
+ // Lower level helpers.
+ void OnGotAppCacheInfo(int rv);
+ void OnAppCacheDeleted(int rv);
+ ChromeAppCacheService* GetAppCacheService();
+
// Calculate the begin time for the deletion range specified by |time_period|.
base::Time CalculateBeginDeleteTime(TimePeriod time_period);
// Returns true if we're all done.
bool all_done() {
return registrar_.IsEmpty() && !waiting_for_clear_cache_ &&
- !waiting_for_clear_history_ && !waiting_for_clear_databases_;
+ !waiting_for_clear_history_ && !waiting_for_clear_databases_ &&
+ !waiting_for_clear_appcache_;
}
NotificationRegistrar registrar_;
@@ -132,14 +146,18 @@ class BrowsingDataRemover : public NotificationObserver {
net::CompletionCallbackImpl<BrowsingDataRemover> database_cleared_callback_;
- // True if we're waiting for HTML5 databases to be deleted.
- bool waiting_for_clear_databases_;
+ // Used to clear the appcache.
+ net::CompletionCallbackImpl<BrowsingDataRemover> appcache_got_info_callback_;
+ net::CompletionCallbackImpl<BrowsingDataRemover> appcache_deleted_callback_;
+ scoped_refptr<appcache::AppCacheInfoCollection> appcache_info_;
+ scoped_refptr<URLRequestContextGetter> request_context_getter_;
+ int appcaches_to_be_deleted_count_;
- // True if we're waiting for the history to be deleted.
+ // True if we're waiting for various data to be deleted.
+ bool waiting_for_clear_databases_;
bool waiting_for_clear_history_;
-
- // True if we're waiting for the cache to be cleared.
bool waiting_for_clear_cache_;
+ bool waiting_for_clear_appcache_;
ObserverList<Observer> observer_list_;
diff --git a/chrome/browser/cookies_tree_model.cc b/chrome/browser/cookies_tree_model.cc
index d884b11..3fd2fca 100644
--- a/chrome/browser/cookies_tree_model.cc
+++ b/chrome/browser/cookies_tree_model.cc
@@ -131,14 +131,15 @@ class OriginNodeComparator {
// CookieTreeAppCacheNode, public:
CookieTreeAppCacheNode::CookieTreeAppCacheNode(
- const BrowsingDataAppCacheHelper::AppCacheInfo* appcache_info)
+ const appcache::AppCacheInfo* appcache_info)
: CookieTreeNode(UTF8ToWide(appcache_info->manifest_url.spec())),
appcache_info_(appcache_info) {
}
void CookieTreeAppCacheNode::DeleteStoredObjects() {
DCHECK(GetModel()->appcache_helper_);
- GetModel()->appcache_helper_->DeleteAppCache(appcache_info_->group_id);
+ GetModel()->appcache_helper_->DeleteAppCacheGroup(
+ appcache_info_->manifest_url);
}
///////////////////////////////////////////////////////////////////////////////
@@ -441,27 +442,37 @@ void CookiesTreeModel::RemoveObserver(Observer* observer) {
}
void CookiesTreeModel::OnAppCacheModelInfoLoaded() {
+ appcache_info_ = appcache_helper_->info_collection();
PopulateAppCacheInfoWithFilter(std::wstring());
}
void CookiesTreeModel::PopulateAppCacheInfoWithFilter(
const std::wstring& filter) {
- if (!appcache_helper_ || appcache_helper_->info_list().empty())
+ using appcache::AppCacheInfo;
+ using appcache::AppCacheInfoVector;
+ typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin;
+
+ if (!appcache_info_ || appcache_info_->infos_by_origin.empty())
return;
+
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
NotifyObserverBeginBatch();
- for (AppCacheInfoList::const_iterator info =
- appcache_helper_->info_list().begin();
- info != appcache_helper_->info_list().end(); ++info) {
- std::wstring origin_node_name = UTF8ToWide(info->manifest_url.host());
+ for (InfoByOrigin::const_iterator origin =
+ appcache_info_->infos_by_origin.begin();
+ origin != appcache_info_->infos_by_origin.end(); ++origin) {
+ std::wstring origin_node_name = UTF8ToWide(origin->first.host());
if (filter.empty() ||
(origin_node_name.find(filter) != std::wstring::npos)) {
CookieTreeOriginNode* origin_node =
root->GetOrCreateOriginNode(origin_node_name);
CookieTreeAppCachesNode* appcaches_node =
origin_node->GetOrCreateAppCachesNode();
- appcaches_node->AddAppCacheNode(
- new CookieTreeAppCacheNode(&(*info)));
+
+ for (AppCacheInfoVector::const_iterator info = origin->second.begin();
+ info != origin->second.end(); ++info) {
+ appcaches_node->AddAppCacheNode(
+ new CookieTreeAppCacheNode(&(*info)));
+ }
}
}
NotifyObserverTreeNodeChanged(root);
diff --git a/chrome/browser/cookies_tree_model.h b/chrome/browser/cookies_tree_model.h
index 056fe5f..50f2e4a 100644
--- a/chrome/browser/cookies_tree_model.h
+++ b/chrome/browser/cookies_tree_model.h
@@ -57,7 +57,7 @@ class CookieTreeNode : public TreeNode<CookieTreeNode> {
const BrowsingDataDatabaseHelper::DatabaseInfo* database_info,
const BrowsingDataLocalStorageHelper::LocalStorageInfo*
local_storage_info,
- const BrowsingDataAppCacheHelper::AppCacheInfo* appcache_info)
+ const appcache::AppCacheInfo* appcache_info)
: origin(origin),
node_type(node_type),
cookie(cookie),
@@ -74,7 +74,7 @@ class CookieTreeNode : public TreeNode<CookieTreeNode> {
const net::CookieMonster::CookieListPair* cookie;
const BrowsingDataDatabaseHelper::DatabaseInfo* database_info;
const BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info;
- const BrowsingDataAppCacheHelper::AppCacheInfo* appcache_info;
+ const appcache::AppCacheInfo* appcache_info;
};
CookieTreeNode() {}
@@ -217,7 +217,7 @@ class CookieTreeAppCacheNode : public CookieTreeNode {
// Does not take ownership of appcache_info, and appcache_info should remain
// valid at least as long as the CookieTreeAppCacheNode is valid.
explicit CookieTreeAppCacheNode(
- const BrowsingDataAppCacheHelper::AppCacheInfo* appcache_info);
+ const appcache::AppCacheInfo* appcache_info);
virtual ~CookieTreeAppCacheNode() {}
virtual void DeleteStoredObjects();
@@ -228,7 +228,7 @@ class CookieTreeAppCacheNode : public CookieTreeNode {
}
private:
- const BrowsingDataAppCacheHelper::AppCacheInfo* appcache_info_;
+ const appcache::AppCacheInfo* appcache_info_;
DISALLOW_COPY_AND_ASSIGN(CookieTreeAppCacheNode);
};
@@ -398,8 +398,6 @@ class CookiesTreeModel : public TreeNodeModel<CookieTreeNode> {
};
typedef net::CookieMonster::CookieList CookieList;
typedef std::vector<net::CookieMonster::CookieListPair*> CookiePtrList;
- typedef std::vector<BrowsingDataAppCacheHelper::AppCacheInfo>
- AppCacheInfoList;
typedef std::vector<BrowsingDataDatabaseHelper::DatabaseInfo>
DatabaseInfoList;
typedef std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo>
@@ -427,6 +425,7 @@ class CookiesTreeModel : public TreeNodeModel<CookieTreeNode> {
scoped_refptr<BrowsingDataAppCacheHelper> appcache_helper_;
scoped_refptr<BrowsingDataDatabaseHelper> database_helper_;
+ scoped_refptr<appcache::AppCacheInfoCollection> appcache_info_;
DatabaseInfoList database_info_list_;
scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper_;
diff --git a/chrome/browser/gtk/gtk_chrome_cookie_view.cc b/chrome/browser/gtk/gtk_chrome_cookie_view.cc
index b6a6728..9c03994 100644
--- a/chrome/browser/gtk/gtk_chrome_cookie_view.cc
+++ b/chrome/browser/gtk/gtk_chrome_cookie_view.cc
@@ -432,7 +432,7 @@ void gtk_chrome_cookie_view_display_local_storage(
// Switches the display to showing the passed in app cache.
void gtk_chrome_cookie_view_display_app_cache(
GtkChromeCookieView* self,
- const BrowsingDataAppCacheHelper::AppCacheInfo& info) {
+ const appcache::AppCacheInfo& info) {
UpdateVisibleDetailedInfo(self, self->appcache_details_table_);
gtk_entry_set_text(GTK_ENTRY(self->appcache_manifest_entry_),
diff --git a/chrome/browser/gtk/gtk_chrome_cookie_view.h b/chrome/browser/gtk/gtk_chrome_cookie_view.h
index 2716eeb..ce157bf 100644
--- a/chrome/browser/gtk/gtk_chrome_cookie_view.h
+++ b/chrome/browser/gtk/gtk_chrome_cookie_view.h
@@ -141,7 +141,7 @@ void gtk_chrome_cookie_view_display_local_storage(
// Switches the display to showing the passed in app cache.
void gtk_chrome_cookie_view_display_app_cache(
GtkChromeCookieView* widget,
- const BrowsingDataAppCacheHelper::AppCacheInfo& info);
+ const appcache::AppCacheInfo& info);
// Switches the display to an individual storage item.
void gtk_chrome_cookie_view_display_local_storage_item(
diff --git a/chrome/browser/mock_browsing_data_appcache_helper.cc b/chrome/browser/mock_browsing_data_appcache_helper.cc
index 1dccff4..e056004 100644
--- a/chrome/browser/mock_browsing_data_appcache_helper.cc
+++ b/chrome/browser/mock_browsing_data_appcache_helper.cc
@@ -24,6 +24,7 @@ void MockBrowsingDataAppCacheHelper::CancelNotification() {
completion_callback_.reset(NULL);
}
-void MockBrowsingDataAppCacheHelper::DeleteAppCache(int64 group_id) {
+void MockBrowsingDataAppCacheHelper::DeleteAppCacheGroup(
+ const GURL& manifest_url) {
}
diff --git a/chrome/browser/mock_browsing_data_appcache_helper.h b/chrome/browser/mock_browsing_data_appcache_helper.h
index 6dc6607..e5b3630 100644
--- a/chrome/browser/mock_browsing_data_appcache_helper.h
+++ b/chrome/browser/mock_browsing_data_appcache_helper.h
@@ -17,7 +17,7 @@ class MockBrowsingDataAppCacheHelper
virtual void StartFetching(Callback0::Type* completion_callback);
virtual void CancelNotification();
- virtual void DeleteAppCache(int64 group_id);
+ virtual void DeleteAppCacheGroup(const GURL& manifest_url);
private:
virtual ~MockBrowsingDataAppCacheHelper();
diff --git a/chrome/browser/views/appcache_info_view.cc b/chrome/browser/views/appcache_info_view.cc
index fd23e7f..4de638c 100755
--- a/chrome/browser/views/appcache_info_view.cc
+++ b/chrome/browser/views/appcache_info_view.cc
@@ -29,8 +29,7 @@ AppCacheInfoView::AppCacheInfoView()
AppCacheInfoView::~AppCacheInfoView() {
}
-void AppCacheInfoView::SetAppCacheInfo(
- const BrowsingDataAppCacheHelper::AppCacheInfo* info) {
+void AppCacheInfoView::SetAppCacheInfo(const appcache::AppCacheInfo* info) {
DCHECK(info);
manifest_url_field_->SetText(UTF8ToWide(info->manifest_url.spec()));
size_field_->SetText(
diff --git a/chrome/browser/views/appcache_info_view.h b/chrome/browser/views/appcache_info_view.h
index ad209d0..25db5dd 100755
--- a/chrome/browser/views/appcache_info_view.h
+++ b/chrome/browser/views/appcache_info_view.h
@@ -26,7 +26,7 @@ class AppCacheInfoView : public views::View {
AppCacheInfoView();
virtual ~AppCacheInfoView();
- void SetAppCacheInfo(const BrowsingDataAppCacheHelper::AppCacheInfo* info);
+ void SetAppCacheInfo(const appcache::AppCacheInfo* info);
void ClearAppCacheDisplay();
void EnableAppCacheDisplay(bool enabled);
diff --git a/webkit/appcache/appcache_group.cc b/webkit/appcache/appcache_group.cc
index 8063b911..0f9b4af 100644
--- a/webkit/appcache/appcache_group.cc
+++ b/webkit/appcache/appcache_group.cc
@@ -41,6 +41,7 @@ AppCacheGroup::AppCacheGroup(AppCacheService* service,
manifest_url_(manifest_url),
update_status_(IDLE),
is_obsolete_(false),
+ is_being_deleted_(false),
newest_complete_cache_(NULL),
update_job_(NULL),
service_(service),
@@ -137,9 +138,8 @@ void AppCacheGroup::RemoveCache(AppCache* cache) {
void AppCacheGroup::AddNewlyDeletableResponseIds(
std::vector<int64>* response_ids) {
- if (!is_obsolete() && old_caches_.empty()) {
- service_->storage()->DeleteResponses(
- manifest_url_, *response_ids);
+ if (is_being_deleted() || (!is_obsolete() && old_caches_.empty())) {
+ service_->storage()->DeleteResponses(manifest_url_, *response_ids);
response_ids->clear();
return;
}
@@ -156,6 +156,7 @@ void AppCacheGroup::AddNewlyDeletableResponseIds(
void AppCacheGroup::StartUpdateWithNewMasterEntry(
AppCacheHost* host, const GURL& new_master_resource) {
+ DCHECK(!is_obsolete() && !is_being_deleted());
if (is_in_dtor_)
return;
@@ -172,6 +173,14 @@ void AppCacheGroup::StartUpdateWithNewMasterEntry(
}
}
+void AppCacheGroup::CancelUpdate() {
+ if (update_job_) {
+ delete update_job_;
+ DCHECK(!update_job_);
+ DCHECK_EQ(IDLE, update_status_);
+ }
+}
+
void AppCacheGroup::QueueUpdate(AppCacheHost* host,
const GURL& new_master_resource) {
DCHECK(update_job_ && host && !new_master_resource.is_empty());
@@ -208,7 +217,7 @@ void AppCacheGroup::RunQueuedUpdates() {
observers_.AddObserver(host);
}
- if (!is_obsolete())
+ if (!is_obsolete() && !is_being_deleted())
StartUpdateWithNewMasterEntry(host, it->second);
}
}
diff --git a/webkit/appcache/appcache_group.h b/webkit/appcache/appcache_group.h
index 1558b5a8..c1bb1fc 100644
--- a/webkit/appcache/appcache_group.h
+++ b/webkit/appcache/appcache_group.h
@@ -55,6 +55,9 @@ class AppCacheGroup : public base::RefCounted<AppCacheGroup> {
bool is_obsolete() const { return is_obsolete_; }
void set_obsolete(bool value) { is_obsolete_ = value; }
+ bool is_being_deleted() const { return is_being_deleted_; }
+ void set_being_deleted(bool value) { is_being_deleted_ = value; }
+
AppCache* newest_complete_cache() const { return newest_complete_cache_; }
void AddCache(AppCache* complete_cache);
@@ -81,6 +84,9 @@ class AppCacheGroup : public base::RefCounted<AppCacheGroup> {
void StartUpdateWithNewMasterEntry(AppCacheHost* host,
const GURL& new_master_resource);
+ // Cancels an update if one is running.
+ void CancelUpdate();
+
private:
class HostObserver;
@@ -113,6 +119,7 @@ class AppCacheGroup : public base::RefCounted<AppCacheGroup> {
const GURL manifest_url_;
UpdateStatus update_status_;
bool is_obsolete_;
+ bool is_being_deleted_;
std::vector<int64> newly_deletable_response_ids_;
// Old complete app caches.
diff --git a/webkit/appcache/appcache_host.cc b/webkit/appcache/appcache_host.cc
index 9d1bf9c..4fb098f 100644
--- a/webkit/appcache/appcache_host.cc
+++ b/webkit/appcache/appcache_host.cc
@@ -142,7 +142,7 @@ void AppCacheHost::DoPendingStartUpdate() {
bool success = false;
if (associated_cache_ && associated_cache_->owning_group()) {
AppCacheGroup* group = associated_cache_->owning_group();
- if (!group->is_obsolete()) {
+ if (!group->is_obsolete() && !group->is_being_deleted()) {
success = true;
group->StartUpdate();
}
@@ -235,7 +235,7 @@ void AppCacheHost::LoadOrCreateGroup(const GURL& manifest_url) {
}
void AppCacheHost::OnGroupLoaded(AppCacheGroup* group,
- const GURL& manifest_url) {
+ const GURL& manifest_url) {
DCHECK(manifest_url == pending_selected_manifest_url_);
pending_selected_manifest_url_ = GURL();
FinishCacheSelection(NULL, group);
@@ -270,11 +270,12 @@ void AppCacheHost::FinishCacheSelection(
DCHECK(cache->owning_group());
DCHECK(new_master_entry_url_.is_empty());
AssociateCache(cache);
- if (!cache->owning_group()->is_obsolete()) {
- cache->owning_group()->StartUpdateWithHost(this);
- ObserveGroupBeingUpdated(cache->owning_group());
+ AppCacheGroup* owing_group = cache->owning_group();
+ if (!owing_group->is_obsolete() && !owing_group->is_being_deleted()) {
+ owing_group->StartUpdateWithHost(this);
+ ObserveGroupBeingUpdated(owing_group);
}
- } else if (group) {
+ } else if (group && !group->is_being_deleted()) {
// If document was loaded using HTTP GET or equivalent, and, there is a
// manifest URL, and manifest URL has the same origin as document.
// Invoke the application cache update process for manifest URL, with
@@ -287,6 +288,7 @@ void AppCacheHost::FinishCacheSelection(
ObserveGroupBeingUpdated(group);
} else {
// Otherwise, the Document is not associated with any application cache.
+ new_master_entry_url_ = GURL();
AssociateCache(NULL);
}
diff --git a/webkit/appcache/appcache_service.cc b/webkit/appcache/appcache_service.cc
index 65cc457..a6bc24a 100644
--- a/webkit/appcache/appcache_service.cc
+++ b/webkit/appcache/appcache_service.cc
@@ -5,17 +5,142 @@
#include "webkit/appcache/appcache_service.h"
#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/stl_util-inl.h"
#include "webkit/appcache/appcache_backend_impl.h"
#include "webkit/appcache/appcache_storage_impl.h"
namespace appcache {
+// AsyncHelper -------
+
+class AppCacheService::AsyncHelper
+ : public AppCacheStorage::Delegate {
+ public:
+ AsyncHelper(
+ AppCacheService* service, net::CompletionCallback* callback)
+ : service_(service), callback_(callback) {
+ service_->pending_helpers_.insert(this);
+ }
+
+ virtual ~AsyncHelper() {
+ if (service_)
+ service_->pending_helpers_.erase(this);
+ }
+
+ virtual void Start() = 0;
+ virtual void Cancel();
+
+ protected:
+ void CallCallback(int rv) {
+ if (callback_) {
+ // Defer to guarentee async completion.
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(&DeferredCallCallback, callback_, rv));
+ }
+ callback_ = NULL;
+ }
+
+ static void DeferredCallCallback(net::CompletionCallback* callback, int rv) {
+ callback->Run(rv);
+ }
+
+ AppCacheService* service_;
+ net::CompletionCallback* callback_;
+};
+
+void AppCacheService::AsyncHelper::Cancel() {
+ CallCallback(net::ERR_ABORTED);
+ service_->storage()->CancelDelegateCallbacks(this);
+ service_ = NULL;
+}
+
+// DeleteHelper -------
+
+class AppCacheService::DeleteHelper : public AsyncHelper {
+ public:
+ DeleteHelper(
+ AppCacheService* service, const GURL& manifest_url,
+ net::CompletionCallback* callback)
+ : AsyncHelper(service, callback), manifest_url_(manifest_url) {
+ }
+
+ virtual void Start() {
+ service_->storage()->LoadOrCreateGroup(manifest_url_, this);
+ }
+
+ private:
+ // AppCacheStorage::Delegate methods
+ virtual void OnGroupLoaded(
+ appcache::AppCacheGroup* group, const GURL& manifest_url);
+ virtual void OnGroupMadeObsolete(
+ appcache::AppCacheGroup* group, bool success);
+
+ GURL manifest_url_;
+};
+
+void AppCacheService::DeleteHelper::OnGroupLoaded(
+ appcache::AppCacheGroup* group, const GURL& manifest_url) {
+ if (group) {
+ group->set_being_deleted(true);
+ group->CancelUpdate();
+ service_->storage()->MakeGroupObsolete(group, this);
+ } else {
+ CallCallback(net::ERR_FAILED);
+ delete this;
+ }
+}
+
+void AppCacheService::DeleteHelper::OnGroupMadeObsolete(
+ appcache::AppCacheGroup* group, bool success) {
+ CallCallback(success ? net::OK : net::ERR_FAILED);
+ delete this;
+}
+
+// GetInfoHelper -------
+
+class AppCacheService::GetInfoHelper : AsyncHelper {
+ public:
+ GetInfoHelper(
+ AppCacheService* service, AppCacheInfoCollection* collection,
+ net::CompletionCallback* callback)
+ : AsyncHelper(service, callback), collection_(collection) {
+ }
+
+ virtual void Start() {
+ service_->storage()->GetAllInfo(this);
+ }
+
+ private:
+ // AppCacheStorage::Delegate override
+ virtual void OnAllInfo(AppCacheInfoCollection* collection);
+
+ scoped_refptr<AppCacheInfoCollection> collection_;
+};
+
+void AppCacheService::GetInfoHelper::OnAllInfo(
+ AppCacheInfoCollection* collection) {
+ if (collection)
+ collection->infos_by_origin.swap(collection_->infos_by_origin);
+ CallCallback(collection ? net::OK : net::ERR_FAILED);
+ delete this;
+}
+
+
+// AppCacheService -------
+
AppCacheService::AppCacheService()
: appcache_policy_(NULL), request_context_(NULL) {
}
AppCacheService::~AppCacheService() {
DCHECK(backends_.empty());
+
+ std::for_each(pending_helpers_.begin(),
+ pending_helpers_.end(),
+ std::mem_fun(&AsyncHelper::Cancel));
+ STLDeleteElements(&pending_helpers_);
}
void AppCacheService::Initialize(const FilePath& cache_directory) {
@@ -25,6 +150,19 @@ void AppCacheService::Initialize(const FilePath& cache_directory) {
storage_.reset(storage);
}
+void AppCacheService::GetAllAppCacheInfo(AppCacheInfoCollection* collection,
+ net::CompletionCallback* callback) {
+ DCHECK(collection);
+ GetInfoHelper* helper = new GetInfoHelper(this, collection, callback);
+ helper->Start();
+}
+
+void AppCacheService::DeleteAppCacheGroup(const GURL& manifest_url,
+ net::CompletionCallback* callback) {
+ DeleteHelper* helper = new DeleteHelper(this, manifest_url, callback);
+ helper->Start();
+}
+
void AppCacheService::RegisterBackend(
AppCacheBackendImpl* backend_impl) {
DCHECK(backends_.find(backend_impl->process_id()) == backends_.end());
diff --git a/webkit/appcache/appcache_service.h b/webkit/appcache/appcache_service.h
index 70a0953..7ccdeea 100644
--- a/webkit/appcache/appcache_service.h
+++ b/webkit/appcache/appcache_service.h
@@ -5,8 +5,15 @@
#ifndef WEBKIT_APPCACHE_APPCACHE_SERVICE_H_
#define WEBKIT_APPCACHE_APPCACHE_SERVICE_H_
+#include <set>
+#include <vector>
+
#include "base/file_path.h"
+#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
#include "webkit/appcache/appcache_storage.h"
@@ -17,6 +24,36 @@ namespace appcache {
class AppCacheBackendImpl;
class AppCachePolicy;
+// Structure that contains basic info about an appcache.
+struct AppCacheInfo {
+ AppCacheInfo() {}
+ AppCacheInfo(const GURL& manifest_url,
+ int64 size,
+ base::Time creation_time,
+ base::Time last_access_time,
+ base::Time last_update_time)
+ : manifest_url(manifest_url),
+ size(size),
+ creation_time(creation_time),
+ last_access_time(last_access_time),
+ last_update_time(last_update_time) {
+ }
+ GURL manifest_url;
+ int64 size;
+ base::Time creation_time;
+ base::Time last_access_time;
+ base::Time last_update_time;
+};
+
+typedef std::vector<AppCacheInfo> AppCacheInfoVector;
+
+// Refcounted container to avoid copying the collection in callbacks.
+struct AppCacheInfoCollection
+ : public base::RefCountedThreadSafe<AppCacheInfoCollection> {
+ virtual ~AppCacheInfoCollection() {}
+ std::map<GURL, AppCacheInfoVector> infos_by_origin;
+};
+
// Class that manages the application cache service. Sends notifications
// to many frontends. One instance per user-profile. Each instance has
// exclusive access to it's cache_directory on disk.
@@ -27,11 +64,27 @@ class AppCacheService {
void Initialize(const FilePath& cache_directory);
+ // Purges any memory not needed.
void PurgeMemory() {
if (storage_.get())
storage_->PurgeMemory();
}
+ // Populates 'collection' with info about all of the appcaches stored
+ // within the service, 'callback' is invoked upon completion. The service
+ // acquires a reference to the 'collection' until until completion.
+ // This method always completes asynchronously.
+ void GetAllAppCacheInfo(AppCacheInfoCollection* collection,
+ net::CompletionCallback* callback);
+
+ // Deletes the group identified by 'manifest_url', 'callback' is
+ // invoked upon completion. Upon completion, the cache group and
+ // any resources within the group are no longer loadable and all
+ // subresource loads for pages associated with a deleted group
+ // will fail. This method always completes asynchronously.
+ void DeleteAppCacheGroup(const GURL& manifest_url,
+ net::CompletionCallback* callback);
+
// Context for use during cache updates, should only be accessed
// on the IO thread. We do NOT add a reference to the request context,
// it is the callers responsibility to ensure that the pointer
@@ -49,7 +102,8 @@ class AppCacheService {
appcache_policy_ = policy;
}
- // Track which processes are using this appcache service.
+ // Each child process in chrome uses a distinct backend instance.
+ // See chrome/browser/AppCacheDispatcherHost.
void RegisterBackend(AppCacheBackendImpl* backend_impl);
void UnregisterBackend(AppCacheBackendImpl* backend_impl);
AppCacheBackendImpl* GetBackend(int id) const {
@@ -60,11 +114,19 @@ class AppCacheService {
AppCacheStorage* storage() const { return storage_.get(); }
protected:
+ class AsyncHelper;
+ class DeleteHelper;
+ class GetInfoHelper;
+
+ typedef std::set<AsyncHelper*> PendingAsyncHelpers;
+
AppCachePolicy* appcache_policy_;
// Deals with persistence.
scoped_ptr<AppCacheStorage> storage_;
+ PendingAsyncHelpers pending_helpers_;
+
// Track current processes. One 'backend' per child process.
typedef std::map<int, AppCacheBackendImpl*> BackendMap;
BackendMap backends_;
diff --git a/webkit/appcache/appcache_storage.h b/webkit/appcache/appcache_storage.h
index 4c51e39..5618be4 100644
--- a/webkit/appcache/appcache_storage.h
+++ b/webkit/appcache/appcache_storage.h
@@ -26,6 +26,7 @@ class AppCacheGroup;
class AppCacheResponseReader;
class AppCacheResponseWriter;
class AppCacheService;
+struct AppCacheInfoCollection;
struct HttpResponseInfoIOBuffer;
class AppCacheStorage {
@@ -35,6 +36,9 @@ class AppCacheStorage {
public:
virtual ~Delegate() {}
+ // If retrieval fails, 'collection' will be NULL.
+ virtual void OnAllInfo(AppCacheInfoCollection* collection) {}
+
// If a load fails the 'cache' will be NULL.
virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) {}
@@ -65,6 +69,11 @@ class AppCacheStorage {
explicit AppCacheStorage(AppCacheService* service);
virtual ~AppCacheStorage();
+ // Schedules a task to retrieve basic info about all groups and caches
+ // stored in the system. Upon completion the delegate will be called
+ // with the results.
+ virtual void GetAllInfo(Delegate* delegate) = 0;
+
// Schedules a cache to be loaded from storage. Upon load completion
// the delegate will be called back. If the cache already resides in
// memory, the delegate will be called back immediately without returning
diff --git a/webkit/appcache/appcache_storage_impl.cc b/webkit/appcache/appcache_storage_impl.cc
index 6fd5486..54afc9a 100644
--- a/webkit/appcache/appcache_storage_impl.cc
+++ b/webkit/appcache/appcache_storage_impl.cc
@@ -183,6 +183,49 @@ class AppCacheStorageImpl::DisableDatabaseTask : public DatabaseTask {
virtual void Run() { database_->Disable(); }
};
+// GetAllInfoTask -------
+
+class AppCacheStorageImpl::GetAllInfoTask : public DatabaseTask {
+ public:
+ explicit GetAllInfoTask(AppCacheStorageImpl* storage)
+ : DatabaseTask(storage),
+ info_collection_(new AppCacheInfoCollection()) {
+ }
+
+ virtual void Run();
+ virtual void RunCompleted();
+
+ scoped_refptr<AppCacheInfoCollection> info_collection_;
+};
+
+void AppCacheStorageImpl::GetAllInfoTask::Run() {
+ std::set<GURL> origins;
+ database_->FindOriginsWithGroups(&origins);
+ for (std::set<GURL>::const_iterator origin = origins.begin();
+ origin != origins.end(); ++origin) {
+ AppCacheInfoVector& infos =
+ info_collection_->infos_by_origin[*origin];
+ std::vector<AppCacheDatabase::GroupRecord> groups;
+ database_->FindGroupsForOrigin(*origin, &groups);
+ for (std::vector<AppCacheDatabase::GroupRecord>::const_iterator
+ group = groups.begin();
+ group != groups.end(); ++group) {
+ AppCacheDatabase::CacheRecord cache_record;
+ database_->FindCacheForGroup(group->group_id, &cache_record);
+ infos.push_back(
+ AppCacheInfo(
+ group->manifest_url, cache_record.cache_size,
+ group->creation_time, group->last_access_time,
+ cache_record.update_time));
+ }
+ }
+}
+
+void AppCacheStorageImpl::GetAllInfoTask::RunCompleted() {
+ DCHECK(delegates_.size() == 1);
+ FOR_EACH_DELEGATE(delegates_, OnAllInfo(info_collection_));
+}
+
// StoreOrLoadTask -------
class AppCacheStorageImpl::StoreOrLoadTask : public DatabaseTask {
@@ -812,6 +855,13 @@ void AppCacheStorageImpl::Disable() {
task->Schedule();
}
+void AppCacheStorageImpl::GetAllInfo(Delegate* delegate) {
+ DCHECK(delegate);
+ scoped_refptr<GetAllInfoTask> task = new GetAllInfoTask(this);
+ task->AddDelegate(GetOrCreateDelegateReference(delegate));
+ task->Schedule();
+}
+
void AppCacheStorageImpl::LoadCache(int64 id, Delegate* delegate) {
DCHECK(delegate);
if (is_disabled_) {
@@ -993,6 +1043,17 @@ void AppCacheStorageImpl::FindResponseForSubRequest(
AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
bool* found_network_namespace) {
DCHECK(cache && cache->is_complete());
+
+ // When a group is forcibly deleted, all subresource loads for pages
+ // using caches in the group will result in a synthesized network errors.
+ // Forcible deletion is not a function that is covered by the HTML5 spec.
+ if (cache->owning_group()->is_being_deleted()) {
+ *found_entry = AppCacheEntry();
+ *found_fallback_entry = AppCacheEntry();
+ *found_network_namespace = false;
+ return;
+ }
+
GURL fallback_namespace_not_used;
cache->FindResponseForRequest(
url, found_entry, found_fallback_entry,
diff --git a/webkit/appcache/appcache_storage_impl.h b/webkit/appcache/appcache_storage_impl.h
index b644eff..5771dd4 100644
--- a/webkit/appcache/appcache_storage_impl.h
+++ b/webkit/appcache/appcache_storage_impl.h
@@ -27,7 +27,8 @@ class AppCacheStorageImpl : public AppCacheStorage {
void Disable();
bool is_disabled() const { return is_disabled_; }
- // AppCacheStorage methods
+ // AppCacheStorage methods, see the base class for doc comments.
+ virtual void GetAllInfo(Delegate* delegate);
virtual void LoadCache(int64 id, Delegate* delegate);
virtual void LoadOrCreateGroup(const GURL& manifest_url, Delegate* delegate);
virtual void StoreGroupAndNewestCache(
@@ -59,6 +60,7 @@ class AppCacheStorageImpl : public AppCacheStorage {
class InitTask;
class CloseConnectionTask;
class DisableDatabaseTask;
+ class GetAllInfoTask;
class StoreOrLoadTask;
class CacheLoadTask;
class GroupLoadTask;
diff --git a/webkit/appcache/mock_appcache_storage.h b/webkit/appcache/mock_appcache_storage.h
index 48834bd..10bd780 100644
--- a/webkit/appcache/mock_appcache_storage.h
+++ b/webkit/appcache/mock_appcache_storage.h
@@ -28,6 +28,7 @@ class MockAppCacheStorage : public AppCacheStorage {
explicit MockAppCacheStorage(AppCacheService* service);
virtual ~MockAppCacheStorage();
+ virtual void GetAllInfo(Delegate* delegate) {} // not implemented
virtual void LoadCache(int64 id, Delegate* delegate);
virtual void LoadOrCreateGroup(const GURL& manifest_url, Delegate* delegate);
virtual void StoreGroupAndNewestCache(