summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-25 14:38:32 +0000
committerjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-25 14:38:32 +0000
commitc10da4b052a8ba91fc76455d3cc2e50e3bc2b08d (patch)
tree25fdd97cc5c3366ff50093088f7531f403f6c9b9
parent11abcfcb82657d248355fa2f5215a29b3e41a9ae (diff)
downloadchromium_src-c10da4b052a8ba91fc76455d3cc2e50e3bc2b08d.zip
chromium_src-c10da4b052a8ba91fc76455d3cc2e50e3bc2b08d.tar.gz
chromium_src-c10da4b052a8ba91fc76455d3cc2e50e3bc2b08d.tar.bz2
Reland r42467. Clear cookies, local storage and databases when an extension gets uninstalled.
BUG=27938,39177 TEST=Unittest in extension_service_unitttest.cc Review URL: http://codereview.chromium.org/1257005 Patch from Mattias Nissler. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42611 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_data_deleter.cc50
-rw-r--r--chrome/browser/extensions/extension_data_deleter.h62
-rw-r--r--chrome/browser/extensions/extensions_service.cc13
-rw-r--r--chrome/browser/extensions/extensions_service.h3
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc79
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.h2
-rw-r--r--chrome/browser/extensions/user_script_listener_unittest.cc5
-rw-r--r--chrome/browser/in_process_webkit/dom_storage_context.cc14
-rw-r--r--chrome/browser/in_process_webkit/dom_storage_context.h7
-rwxr-xr-xchrome/chrome_browser.gypi2
-rw-r--r--chrome/test/testing_profile.cc29
-rw-r--r--chrome/test/testing_profile.h5
-rw-r--r--net/base/cookie_monster.cc79
-rw-r--r--net/base/cookie_monster.h7
-rw-r--r--webkit/database/database_tracker.cc60
-rw-r--r--webkit/database/database_tracker.h10
16 files changed, 375 insertions, 52 deletions
diff --git a/chrome/browser/extensions/extension_data_deleter.cc b/chrome/browser/extensions/extension_data_deleter.cc
new file mode 100644
index 0000000..98cf433
--- /dev/null
+++ b/chrome/browser/extensions/extension_data_deleter.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 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.
+
+#include "chrome/browser/extensions/extension_data_deleter.h"
+
+#include "chrome/browser/profile.h"
+#include "chrome/common/extensions/extension.h"
+#include "net/base/cookie_monster.h"
+#include "net/base/net_errors.h"
+#include "webkit/database/database_util.h"
+
+ExtensionDataDeleter::ExtensionDataDeleter(Profile* profile,
+ const GURL& extension_url) {
+ DCHECK(profile);
+ webkit_context_ = profile->GetWebKitContext();
+ database_tracker_ = profile->GetDatabaseTracker();
+ extension_request_context_ = profile->GetRequestContextForExtensions();
+ extension_url_ = extension_url;
+ origin_id_ =
+ webkit_database::DatabaseUtil::GetOriginIdentifier(extension_url_);
+}
+
+void ExtensionDataDeleter::StartDeleting() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ net::CookieMonster* cookie_monster =
+ extension_request_context_->GetCookieStore()->GetCookieMonster();
+ if (cookie_monster)
+ cookie_monster->DeleteAllForURL(extension_url_, true);
+
+ ChromeThread::PostTask(ChromeThread::WEBKIT, FROM_HERE,
+ NewRunnableMethod(this,
+ &ExtensionDataDeleter::DeleteLocalStorageOnWebkitThread));
+
+ ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &ExtensionDataDeleter::DeleteDatabaseOnFileThread));
+}
+
+void ExtensionDataDeleter::DeleteDatabaseOnFileThread() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ int rv = database_tracker_->DeleteDataForOrigin(origin_id_, NULL);
+ DCHECK(rv == net::OK || rv == net::ERR_IO_PENDING);
+}
+
+void ExtensionDataDeleter::DeleteLocalStorageOnWebkitThread() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+ webkit_context_->dom_storage_context()->DeleteLocalStorageForOrigin(
+ origin_id_);
+}
diff --git a/chrome/browser/extensions/extension_data_deleter.h b/chrome/browser/extensions/extension_data_deleter.h
new file mode 100644
index 0000000..a886833
--- /dev/null
+++ b/chrome/browser/extensions/extension_data_deleter.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2010 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_EXTENSION_DATA_DELETER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_DATA_DELETER_H_
+
+#include <string>
+
+#include "base/ref_counted.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/in_process_webkit/webkit_context.h"
+#include "chrome/browser/net/url_request_context_getter.h"
+#include "googleurl/src/gurl.h"
+#include "webkit/database/database_tracker.h"
+
+class Extension;
+class Profile;
+
+// A helper class that takes care of removing local storage, databases and
+// cookies for a given extension. This is used by
+// ExtensionsService::ClearExtensionData() upon uninstalling an extension.
+class ExtensionDataDeleter
+ : public base::RefCountedThreadSafe<ExtensionDataDeleter,
+ ChromeThread::DeleteOnUIThread> {
+ public:
+ ExtensionDataDeleter(Profile* profile, const GURL& extension_url);
+
+ // Start removing data. The extension should not be running when this is
+ // called. Cookies are deleted on the current thread, local storage and
+ // databases are deleted asynchronously on the webkit and file threads,
+ // respectively. This function must be called from the UI thread.
+ void StartDeleting();
+
+ private:
+ // Deletes the database for the extension. May only be called on the file
+ // thread.
+ void DeleteDatabaseOnFileThread();
+
+ // Deletes local storage for the extension. May only be called on the webkit
+ // thread.
+ void DeleteLocalStorageOnWebkitThread();
+
+ // The database context for deleting the database.
+ scoped_refptr<webkit_database::DatabaseTracker> database_tracker_;
+
+ // Provides access to the extension request context.
+ scoped_refptr<URLRequestContextGetter> extension_request_context_;
+
+ // The URL of the extension we're removing data for.
+ GURL extension_url_;
+
+ // The security origin identifier for which we're deleting stuff.
+ string16 origin_id_;
+
+ // Webkit context for accessing the DOM storage helper.
+ scoped_refptr<WebKitContext> webkit_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionDataDeleter);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_DATA_DELETER_H_
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 4c3e039..28ba10c 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -19,6 +19,7 @@
#include "chrome/browser/extensions/extension_accessibility_api.h"
#include "chrome/browser/extensions/extension_bookmarks_module.h"
#include "chrome/browser/extensions/extension_browser_event_router.h"
+#include "chrome/browser/extensions/extension_data_deleter.h"
#include "chrome/browser/extensions/extension_dom_ui.h"
#include "chrome/browser/extensions/extension_history_api.h"
#include "chrome/browser/extensions/extension_host.h"
@@ -41,6 +42,7 @@
#include "chrome/common/json_value_serializer.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
#include "webkit/database/database_tracker.h"
#include "webkit/database/database_util.h"
@@ -268,6 +270,7 @@ void ExtensionsService::UninstallExtension(const std::string& extension_id,
// Callers should not send us nonexistant extensions.
DCHECK(extension);
+ GURL extension_url(extension->url());
extension_prefs_->OnExtensionUninstalled(extension, external_uninstall);
@@ -283,7 +286,17 @@ void ExtensionsService::UninstallExtension(const std::string& extension_id,
ExtensionDOMUI::UnregisterChromeURLOverrides(profile_,
extension->GetChromeURLOverrides());
+ // TODO(mnissler, erikkay) Check whether we should really unload the extension
+ // first, so we we're sure it's not running while we clean up.
UnloadExtension(extension_id);
+
+ ClearExtensionData(extension_url);
+}
+
+void ExtensionsService::ClearExtensionData(const GURL& extension_url) {
+ scoped_refptr<ExtensionDataDeleter> deleter(
+ new ExtensionDataDeleter(profile_, extension_url));
+ deleter->StartDeleting();
}
void ExtensionsService::EnableExtension(const std::string& extension_id) {
diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h
index 86737f0..413454c 100644
--- a/chrome/browser/extensions/extensions_service.h
+++ b/chrome/browser/extensions/extensions_service.h
@@ -293,6 +293,9 @@ class ExtensionsService
friend class ChromeThread;
friend class DeleteTask<ExtensionsService>;
+ // Clear all persistent data that may have been stored by the extension.
+ void ClearExtensionData(const GURL& extension_url);
+
// Look up an extension by ID, optionally including either or both of enabled
// and disabled extensions.
Extension* GetExtensionByIdInternal(const std::string& id,
diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc
index a142ca4..ff9a2b6 100644
--- a/chrome/browser/extensions/extensions_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_service_unittest.cc
@@ -39,6 +39,8 @@
#include "testing/platform_test.h"
#include "webkit/database/database_tracker.h"
#include "webkit/database/database_util.h"
+#include "net/base/cookie_monster.h"
+#include "net/base/cookie_options.h"
namespace keys = extension_manifest_keys;
@@ -221,14 +223,17 @@ class ExtensionTestingProfile : public TestingProfile {
ExtensionsServiceTestBase::ExtensionsServiceTestBase()
: loop_(MessageLoop::TYPE_IO),
ui_thread_(ChromeThread::UI, &loop_),
- file_thread_(ChromeThread::FILE, &loop_) {
+ webkit_thread_(ChromeThread::WEBKIT, &loop_),
+ file_thread_(ChromeThread::FILE, &loop_),
+ io_thread_(ChromeThread::IO, &loop_) {
}
ExtensionsServiceTestBase::~ExtensionsServiceTestBase() {
- // Drop our reference to ExtensionsService now, so that it can be destroyed
- // while ChromeThreads and MessageLoop are still around (they are used
- // in the ExtensionsService destruction process).
+ // Drop our reference to ExtensionsService and TestingProfile, so that they
+ // can be destroyed while ChromeThreads and MessageLoop are still around (they
+ // are used in the destruction process).
service_ = NULL;
+ profile_.reset(NULL);
MessageLoop::current()->RunAllPending();
}
@@ -1260,6 +1265,72 @@ TEST_F(ExtensionsServiceTest, UninstallExtension) {
EXPECT_FALSE(file_util::PathExists(extension_path));
}
+// Verifies extension state is removed upon uninstall
+TEST_F(ExtensionsServiceTest, ClearExtensionData) {
+ InitializeEmptyExtensionsService();
+
+ // Load a test extension.
+ FilePath path;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
+ path = path.AppendASCII("extensions");
+ path = path.AppendASCII("good.crx");
+ InstallExtension(path, true);
+ Extension* extension = service_->GetExtensionById(good_crx, false);
+ ASSERT_TRUE(extension);
+ GURL ext_url(extension->url());
+ string16 origin_id =
+ webkit_database::DatabaseUtil::GetOriginIdentifier(ext_url);
+
+ // Set a cookie for the extension.
+ net::CookieMonster* cookie_monster = profile_
+ ->GetRequestContextForExtensions()->GetCookieStore()->GetCookieMonster();
+ ASSERT_TRUE(cookie_monster);
+ net::CookieOptions options;
+ cookie_monster->SetCookieWithOptions(ext_url, "dummy=value", options);
+ net::CookieMonster::CookieList list =
+ cookie_monster->GetAllCookiesForURL(ext_url);
+ EXPECT_EQ(1U, list.size());
+
+ // Open a database.
+ webkit_database::DatabaseTracker* db_tracker = profile_->GetDatabaseTracker();
+ string16 db_name = UTF8ToUTF16("db");
+ string16 description = UTF8ToUTF16("db_description");
+ int64 size;
+ int64 available;
+ db_tracker->DatabaseOpened(origin_id, db_name, description, 1, &size,
+ &available);
+ db_tracker->DatabaseClosed(origin_id, db_name);
+ std::vector<webkit_database::OriginInfo> origins;
+ db_tracker->GetAllOriginsInfo(&origins);
+ EXPECT_EQ(1U, origins.size());
+ EXPECT_EQ(origin_id, origins[0].GetOrigin());
+
+ // Create local storage. We only simulate this by creating the backing file
+ // since webkit is not initialized.
+ DOMStorageContext* context =
+ profile_->GetWebKitContext()->dom_storage_context();
+ FilePath lso_path = context->GetLocalStorageFilePath(origin_id);
+ EXPECT_TRUE(file_util::CreateDirectory(lso_path.DirName()));
+ EXPECT_EQ(0, file_util::WriteFile(lso_path, NULL, 0));
+ EXPECT_TRUE(file_util::PathExists(lso_path));
+
+ // Uninstall the extension.
+ service_->UninstallExtension(good_crx, false);
+ loop_.RunAllPending();
+
+ // Check that the cookie is gone.
+ list = cookie_monster->GetAllCookiesForURL(ext_url);
+ EXPECT_EQ(0U, list.size());
+
+ // The database should have vanished as well.
+ origins.clear();
+ db_tracker->GetAllOriginsInfo(&origins);
+ EXPECT_EQ(0U, origins.size());
+
+ // Check that the LSO file has been removed.
+ EXPECT_FALSE(file_util::PathExists(lso_path));
+}
+
// Tests loading single extensions (like --load-extension)
TEST_F(ExtensionsServiceTest, LoadExtension) {
InitializeEmptyExtensionsService();
diff --git a/chrome/browser/extensions/extensions_service_unittest.h b/chrome/browser/extensions/extensions_service_unittest.h
index 1f24fed..fdb2ddd 100644
--- a/chrome/browser/extensions/extensions_service_unittest.h
+++ b/chrome/browser/extensions/extensions_service_unittest.h
@@ -44,7 +44,9 @@ class ExtensionsServiceTestBase : public testing::Test {
size_t total_successes_;
MessageLoop loop_;
ChromeThread ui_thread_;
+ ChromeThread webkit_thread_;
ChromeThread file_thread_;
+ ChromeThread io_thread_;
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSIONS_SERVICE_UNITTEST_H_
diff --git a/chrome/browser/extensions/user_script_listener_unittest.cc b/chrome/browser/extensions/user_script_listener_unittest.cc
index cd9048c..ec13f9f 100644
--- a/chrome/browser/extensions/user_script_listener_unittest.cc
+++ b/chrome/browser/extensions/user_script_listener_unittest.cc
@@ -107,8 +107,7 @@ class UserScriptListenerTest
: public ExtensionsServiceTestBase,
public URLRequest::Interceptor {
public:
- UserScriptListenerTest()
- : mock_io_thread_(ChromeThread::IO, MessageLoop::current()) {
+ UserScriptListenerTest() {
URLRequest::RegisterRequestInterceptor(this);
}
@@ -171,8 +170,6 @@ class UserScriptListenerTest
scoped_refptr<UserScriptListener> listener_;
private:
- ChromeThread mock_io_thread_;
-
ResourceQueue resource_queue_;
};
diff --git a/chrome/browser/in_process_webkit/dom_storage_context.cc b/chrome/browser/in_process_webkit/dom_storage_context.cc
index 279ecb5..bea4611 100644
--- a/chrome/browser/in_process_webkit/dom_storage_context.cc
+++ b/chrome/browser/in_process_webkit/dom_storage_context.cc
@@ -190,6 +190,11 @@ void DOMStorageContext::DeleteLocalStorageFile(const FilePath& file_path) {
file_util::Delete(file_path, false);
}
+void DOMStorageContext::DeleteLocalStorageForOrigin(const string16& origin_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+ DeleteLocalStorageFile(GetLocalStorageFilePath(origin_id));
+}
+
void DOMStorageContext::DeleteAllLocalStorageFiles() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
@@ -264,3 +269,12 @@ void DOMStorageContext::ClearLocalState(const FilePath& profile_path,
}
}
}
+
+FilePath DOMStorageContext::GetLocalStorageFilePath(
+ const string16& origin_id) const {
+ FilePath storageDir = webkit_context_->data_path().Append(
+ DOMStorageContext::kLocalStorageDirectory);
+ FilePath::StringType id =
+ webkit_glue::WebStringToFilePathString(origin_id);
+ return storageDir.Append(id.append(kLocalStorageExtension));
+}
diff --git a/chrome/browser/in_process_webkit/dom_storage_context.h b/chrome/browser/in_process_webkit/dom_storage_context.h
index 81276c2..2b9e1d1 100644
--- a/chrome/browser/in_process_webkit/dom_storage_context.h
+++ b/chrome/browser/in_process_webkit/dom_storage_context.h
@@ -9,6 +9,7 @@
#include <set>
#include "base/file_path.h"
+#include "base/string16.h"
#include "base/time.h"
class DOMStorageArea;
@@ -70,6 +71,9 @@ class DOMStorageContext {
// Deletes a single local storage file.
void DeleteLocalStorageFile(const FilePath& file_path);
+ // Deletes the local storage file for the given origin.
+ void DeleteLocalStorageForOrigin(const string16& origin_id);
+
// Deletes all local storage files.
void DeleteAllLocalStorageFiles();
@@ -83,6 +87,9 @@ class DOMStorageContext {
static void ClearLocalState(const FilePath& profile_path,
const char* url_scheme_to_be_skipped);
+ // Get the file name of the local storage file for the given origin.
+ FilePath GetLocalStorageFilePath(const string16& origin_id) const;
+
private:
// Get the local storage instance. The object is owned by this class.
DOMStorageNamespace* CreateLocalStorage();
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 7f8f8d7..6284635 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -936,6 +936,8 @@
'browser/extensions/extension_context_menu_model.h',
'browser/extensions/extension_creator.cc',
'browser/extensions/extension_creator.h',
+ 'browser/extensions/extension_data_deleter.cc',
+ 'browser/extensions/extension_data_deleter.h',
'browser/extensions/extension_disabled_infobar_delegate.cc',
'browser/extensions/extension_disabled_infobar_delegate.h',
'browser/extensions/extension_devtools_bridge.cc',
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
index 8fb3a5b..b0be809 100644
--- a/chrome/test/testing_profile.cc
+++ b/chrome/test/testing_profile.cc
@@ -7,6 +7,7 @@
#include "build/build_config.h"
#include "base/command_line.h"
#include "base/string_util.h"
+#include "chrome/common/url_constants.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/dom_ui/ntp_resource_cache.h"
#include "chrome/browser/history/history_backend.h"
@@ -109,6 +110,28 @@ class TestURLRequestContextGetter : public URLRequestContextGetter {
scoped_refptr<URLRequestContext> context_;
};
+class TestExtensionURLRequestContext : public URLRequestContext {
+ public:
+ TestExtensionURLRequestContext() {
+ net::CookieMonster* cookie_monster = new net::CookieMonster(NULL, NULL);
+ const char* schemes[] = {chrome::kExtensionScheme};
+ cookie_monster->SetCookieableSchemes(schemes, 1);
+ cookie_store_ = cookie_monster;
+ }
+};
+
+class TestExtensionURLRequestContextGetter : public URLRequestContextGetter {
+ public:
+ virtual URLRequestContext* GetURLRequestContext() {
+ if (!context_)
+ context_ = new TestExtensionURLRequestContext();
+ return context_.get();
+ }
+
+ private:
+ scoped_refptr<URLRequestContext> context_;
+};
+
} // namespace
TestingProfile::TestingProfile()
@@ -277,6 +300,12 @@ void TestingProfile::CreateRequestContext() {
request_context_ = new TestURLRequestContextGetter();
}
+URLRequestContextGetter* TestingProfile::GetRequestContextForExtensions() {
+ if (!extensions_request_context_)
+ extensions_request_context_ = new TestExtensionURLRequestContextGetter();
+ return extensions_request_context_.get();
+}
+
void TestingProfile::set_session_service(SessionService* session_service) {
session_service_ = session_service;
}
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index 08e02b7..ce1603d 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -179,9 +179,7 @@ class TestingProfile : public Profile {
void CreateRequestContext();
virtual URLRequestContextGetter* GetRequestContextForMedia() { return NULL; }
- virtual URLRequestContextGetter* GetRequestContextForExtensions() {
- return NULL;
- }
+ virtual URLRequestContextGetter* GetRequestContextForExtensions();
virtual net::SSLConfigService* GetSSLConfigService() { return NULL; }
virtual Blacklist* GetPrivacyBlacklist() { return NULL; }
@@ -303,6 +301,7 @@ class TestingProfile : public Profile {
// Internally, this is a TestURLRequestContextGetter that creates a dummy
// request context. Currently, only the CookieMonster is hooked up.
scoped_refptr<URLRequestContextGetter> request_context_;
+ scoped_refptr<URLRequestContextGetter> extensions_request_context_;
// Do we have a history service? This defaults to the value of
// history_service, but can be explicitly set.
diff --git a/net/base/cookie_monster.cc b/net/base/cookie_monster.cc
index 5a1e492..f0cf00a 100644
--- a/net/base/cookie_monster.cc
+++ b/net/base/cookie_monster.cc
@@ -787,6 +787,20 @@ int CookieMonster::DeleteAllCreatedAfter(const Time& delete_begin,
return DeleteAllCreatedBetween(delete_begin, Time(), sync_to_store);
}
+int CookieMonster::DeleteAllForURL(const GURL& url,
+ bool sync_to_store) {
+ AutoLock autolock(lock_);
+ InitIfNecessary();
+ CookieList cookies = InternalGetAllCookiesForURL(url);
+ int num_deleted = 0;
+ for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
+ CookieMap::iterator curit = it;
+ ++it;
+ InternalDeleteCookie(curit, sync_to_store);
+ }
+ return num_deleted;
+}
+
bool CookieMonster::DeleteCookie(const std::string& domain,
const CanonicalCookie& cookie,
bool sync_to_store) {
@@ -916,37 +930,7 @@ CookieMonster::CookieList CookieMonster::GetAllCookies() {
CookieMonster::CookieList CookieMonster::GetAllCookiesForURL(const GURL& url) {
AutoLock autolock(lock_);
InitIfNecessary();
-
- // Do not return removed cookies.
- GarbageCollectExpired(Time::Now(),
- CookieMapItPair(cookies_.begin(), cookies_.end()),
- NULL);
-
- CookieList cookie_list;
- if (!HasCookieableScheme(url))
- return cookie_list;
-
- bool secure = url.SchemeIsSecure();
-
- // Query for the full host, For example: 'a.c.blah.com'.
- std::string key(url.host());
- FindRawCookies(key, secure, url.path(), &cookie_list);
-
- // See if we can search for domain cookies, i.e. if the host has a TLD + 1.
- const std::string domain(GetEffectiveDomain(url.scheme(), key));
- if (domain.empty())
- return cookie_list;
-
- // Use same logic as in FindCookiesForHostAndDomain.
- DCHECK_LE(domain.length(), key.length());
- DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(),
- domain));
- for (key = "." + key; key.length() > domain.length(); ) {
- FindRawCookies(key, secure, url.path(), &cookie_list);
- const size_t next_dot = key.find('.', 1); // Skip over leading dot.
- key.erase(0, next_dot);
- }
- return cookie_list;
+ return InternalGetAllCookiesForURL(url);
}
void CookieMonster::FindCookiesForHostAndDomain(
@@ -1035,6 +1019,39 @@ void CookieMonster::FindRawCookies(const std::string& key,
}
}
+CookieMonster::CookieList CookieMonster::InternalGetAllCookiesForURL(
+ const GURL& url) {
+ // Do not return removed cookies.
+ GarbageCollectExpired(Time::Now(),
+ CookieMapItPair(cookies_.begin(), cookies_.end()),
+ NULL);
+
+ CookieList cookie_list;
+ if (!HasCookieableScheme(url))
+ return cookie_list;
+
+ bool secure = url.SchemeIsSecure();
+
+ // Query for the full host, For example: 'a.c.blah.com'.
+ std::string key(url.host());
+ FindRawCookies(key, secure, url.path(), &cookie_list);
+
+ // See if we can search for domain cookies, i.e. if the host has a TLD + 1.
+ const std::string domain(GetEffectiveDomain(url.scheme(), key));
+ if (domain.empty())
+ return cookie_list;
+
+ // Use same logic as in FindCookiesForHostAndDomain.
+ DCHECK_LE(domain.length(), key.length());
+ DCHECK_EQ(0, key.compare(key.length() - domain.length(), domain.length(),
+ domain));
+ for (key = "." + key; key.length() > domain.length(); ) {
+ FindRawCookies(key, secure, url.path(), &cookie_list);
+ const size_t next_dot = key.find('.', 1); // Skip over leading dot.
+ key.erase(0, next_dot);
+ }
+ return cookie_list;
+}
CookieMonster::ParsedCookie::ParsedCookie(const std::string& cookie_line)
: is_valid_(false),
diff --git a/net/base/cookie_monster.h b/net/base/cookie_monster.h
index ab82056..d421d6f 100644
--- a/net/base/cookie_monster.h
+++ b/net/base/cookie_monster.h
@@ -118,6 +118,9 @@ class CookieMonster : public CookieStore {
// one passed into the function via |delete_after|.
int DeleteAllCreatedAfter(const base::Time& delete_begin, bool sync_to_store);
+ // Delete all cookies that match the given URL.
+ int DeleteAllForURL(const GURL& url, bool sync_to_store);
+
// Delete one specific cookie.
bool DeleteCookie(const std::string& domain,
const CanonicalCookie& cookie,
@@ -182,6 +185,10 @@ class CookieMonster : public CookieStore {
const std::string& path,
CookieList* list);
+ // Internal helper returning all cookies for a given URL. The caller is
+ // assumed to hold lock_ and having called InitIfNecessary().
+ CookieList InternalGetAllCookiesForURL(const GURL& url);
+
// Delete any cookies that are equivalent to |ecc| (same path, key, etc).
// If |skip_httponly| is true, httponly cookies will not be deleted. The
// return value with be true if |skip_httponly| skipped an httponly cookie.
diff --git a/webkit/database/database_tracker.cc b/webkit/database/database_tracker.cc
index bc7dd47..ea1994e 100644
--- a/webkit/database/database_tracker.cc
+++ b/webkit/database/database_tracker.cc
@@ -420,6 +420,22 @@ void DatabaseTracker::ScheduleDatabaseForDeletion(
origin_identifier, database_name));
}
+void DatabaseTracker::ScheduleDatabasesForDeletion(
+ const DatabaseSet& databases,
+ net::CompletionCallback* callback) {
+ DCHECK(!callback ||
+ deletion_callbacks_.find(callback) == deletion_callbacks_.end());
+ DCHECK(!databases.empty());
+ if (callback)
+ deletion_callbacks_[callback] = databases;
+ for (DatabaseSet::const_iterator ori = databases.begin();
+ ori != databases.end(); ++ori) {
+ for (std::set<string16>::const_iterator db = ori->second.begin();
+ db != ori->second.end(); ++db)
+ ScheduleDatabaseForDeletion(ori->first, *db);
+ }
+}
+
int DatabaseTracker::DeleteDatabase(const string16& origin_identifier,
const string16& database_name,
net::CompletionCallback* callback) {
@@ -477,18 +493,42 @@ int DatabaseTracker::DeleteDataModifiedSince(
}
}
+ if (rv != net::OK)
+ return rv;
+
if (!to_be_deleted.empty()) {
- if (callback)
- deletion_callbacks_[callback] = to_be_deleted;
- for (DatabaseSet::iterator ori = to_be_deleted.begin();
- ori != to_be_deleted.end(); ++ori) {
- for (std::set<string16>::iterator db = ori->second.begin();
- db != ori->second.end(); ++db)
- ScheduleDatabaseForDeletion(ori->first, *db);
- }
- rv = net::ERR_IO_PENDING;
+ ScheduleDatabasesForDeletion(to_be_deleted, callback);
+ return net::ERR_IO_PENDING;
+ }
+ return net::OK;
+}
+
+int DatabaseTracker::DeleteDataForOrigin(const string16& origin,
+ net::CompletionCallback* callback) {
+ if (!LazyInit())
+ return net::ERR_FAILED;
+
+ DCHECK(!callback ||
+ deletion_callbacks_.find(callback) == deletion_callbacks_.end());
+ DatabaseSet to_be_deleted;
+
+ std::vector<DatabaseDetails> details;
+ if (!databases_table_->GetAllDatabaseDetailsForOrigin(origin, &details))
+ return net::ERR_FAILED;
+ for (std::vector<DatabaseDetails>::const_iterator db = details.begin();
+ db != details.end(); ++db) {
+ // Check if the database is opened by any renderer.
+ if (database_connections_.IsDatabaseOpened(origin, db->database_name))
+ to_be_deleted[origin].insert(db->database_name);
+ else
+ DeleteClosedDatabase(origin, db->database_name);
}
- return rv;
+
+ if (!to_be_deleted.empty()) {
+ ScheduleDatabasesForDeletion(to_be_deleted, callback);
+ return net::ERR_IO_PENDING;
+ }
+ return net::OK;
}
// static
diff --git a/webkit/database/database_tracker.h b/webkit/database/database_tracker.h
index 90c9ebc..d1d5a43 100644
--- a/webkit/database/database_tracker.h
+++ b/webkit/database/database_tracker.h
@@ -148,6 +148,12 @@ class DatabaseTracker
int DeleteDataModifiedSince(const base::Time& cutoff,
net::CompletionCallback* callback);
+ // Delete all databases that belong to the given origin. Returns net::OK on
+ // success, net::FAILED if not all databases could be deleted, and
+ // net::ERR_IO_PENDING and |callback| is invoked upon completion, if non-NULL.
+ int DeleteDataForOrigin(const string16& origin_identifier,
+ net::CompletionCallback* callback);
+
static void ClearLocalState(const FilePath& profile_path);
private:
@@ -201,6 +207,10 @@ class DatabaseTracker
const string16& database_name);
void ScheduleDatabaseForDeletion(const string16& origin_identifier,
const string16& database_name);
+ // Schedule a set of open databases for deletion. If non-null, callback is
+ // invoked upon completion.
+ void ScheduleDatabasesForDeletion(const DatabaseSet& databases,
+ net::CompletionCallback* callback);
bool initialized_;
const FilePath db_dir_;