diff options
author | marja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-08 11:31:40 +0000 |
---|---|---|
committer | marja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-08 11:31:40 +0000 |
commit | f5d75f7d779dbc8bdc234f24a0c5e0bad1df40b2 (patch) | |
tree | a4781091fde7f14a5167e317811c084a628d25a3 | |
parent | db15183c76bbfd38dc0dc22e61b85c8d18f96e18 (diff) | |
download | chromium_src-f5d75f7d779dbc8bdc234f24a0c5e0bad1df40b2.zip chromium_src-f5d75f7d779dbc8bdc234f24a0c5e0bad1df40b2.tar.gz chromium_src-f5d75f7d779dbc8bdc234f24a0c5e0bad1df40b2.tar.bz2 |
DatabaseTracker: Clearing session-only databases on exit.
BUG=47049
TEST=DatabaseTrackerTest.DatabaseTrackerClearSessionOnlyDatabasesOnExit
Review URL: http://codereview.chromium.org/7800040
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100135 0039d316-1c4b-4281-b951-d872f2087c98
11 files changed, 184 insertions, 9 deletions
diff --git a/chrome/browser/extensions/extension_special_storage_policy.cc b/chrome/browser/extensions/extension_special_storage_policy.cc index 95a2486..de58fb9 100644 --- a/chrome/browser/extensions/extension_special_storage_policy.cc +++ b/chrome/browser/extensions/extension_special_storage_policy.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/common/content_settings.h" +#include "chrome/common/content_settings_types.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/url_constants.h" #include "content/browser/browser_thread.h" @@ -37,6 +38,22 @@ bool ExtensionSpecialStoragePolicy::IsStorageSessionOnly(const GURL& origin) { return (content_setting == CONTENT_SETTING_SESSION_ONLY); } +bool ExtensionSpecialStoragePolicy::HasSessionOnlyOrigins() { + if (host_content_settings_map_ == NULL) + return false; + if (host_content_settings_map_->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_COOKIES) == CONTENT_SETTING_SESSION_ONLY) + return true; + HostContentSettingsMap::SettingsForOneType entries; + host_content_settings_map_->GetSettingsForOneType( + CONTENT_SETTINGS_TYPE_COOKIES, "", &entries); + for (size_t i = 0; i < entries.size(); ++i) { + if (entries[i].c == CONTENT_SETTING_SESSION_ONLY) + return true; + } + return false; +} + bool ExtensionSpecialStoragePolicy::IsFileHandler( const std::string& extension_id) { base::AutoLock locker(lock_); diff --git a/chrome/browser/extensions/extension_special_storage_policy.h b/chrome/browser/extensions/extension_special_storage_policy.h index 8ce9d30..bce392c 100644 --- a/chrome/browser/extensions/extension_special_storage_policy.h +++ b/chrome/browser/extensions/extension_special_storage_policy.h @@ -30,6 +30,7 @@ class ExtensionSpecialStoragePolicy : public quota::SpecialStoragePolicy { virtual bool IsStorageUnlimited(const GURL& origin); virtual bool IsStorageSessionOnly(const GURL& origin); virtual bool IsFileHandler(const std::string& extension_id); + virtual bool HasSessionOnlyOrigins(); // Methods used by the ExtensionService to populate this class. void GrantRightsForExtension(const Extension* extension); diff --git a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc index bd7f274..938b3f9 100644 --- a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc +++ b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc @@ -3,9 +3,13 @@ // found in the LICENSE file. #include "base/values.h" +#include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/extensions/extension_special_storage_policy.h" +#include "chrome/common/content_settings.h" +#include "chrome/common/content_settings_types.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" +#include "chrome/test/base/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" namespace keys = extension_manifest_keys; @@ -210,3 +214,42 @@ TEST_F(ExtensionSpecialStoragePolicyTest, OverlappingApps) { EXPECT_FALSE(policy->IsStorageProtected(GURL("http://foo.wildcards/"))); EXPECT_FALSE(policy->IsStorageProtected(GURL("https://bar.wildcards/"))); } + +TEST_F(ExtensionSpecialStoragePolicyTest, HasSessionOnlyOrigins) { + MessageLoop message_loop; + BrowserThread ui_thread(BrowserThread::UI, &message_loop); + + TestingProfile profile; + HostContentSettingsMap* host_content_settings_map = + profile.GetHostContentSettingsMap(); + scoped_refptr<ExtensionSpecialStoragePolicy> policy( + new ExtensionSpecialStoragePolicy(host_content_settings_map)); + + EXPECT_FALSE(policy->HasSessionOnlyOrigins()); + + // The default setting can be session-only. + host_content_settings_map->SetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_SESSION_ONLY); + EXPECT_TRUE(policy->HasSessionOnlyOrigins()); + + host_content_settings_map->SetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_ALLOW); + EXPECT_FALSE(policy->HasSessionOnlyOrigins()); + + // Or the session-onlyness can affect individual origins. + ContentSettingsPattern pattern = + ContentSettingsPattern::FromString("pattern.com"); + + host_content_settings_map->SetContentSetting( + pattern, ContentSettingsPattern::Wildcard(), + CONTENT_SETTINGS_TYPE_COOKIES, "", CONTENT_SETTING_SESSION_ONLY); + + EXPECT_TRUE(policy->HasSessionOnlyOrigins()); + + // Clearing an origin-spesific rule. + host_content_settings_map->SetContentSetting( + pattern, ContentSettingsPattern::Wildcard(), + CONTENT_SETTINGS_TYPE_COOKIES, "", CONTENT_SETTING_DEFAULT); + + EXPECT_FALSE(policy->HasSessionOnlyOrigins()); +} diff --git a/chrome/browser/extensions/mock_extension_special_storage_policy.cc b/chrome/browser/extensions/mock_extension_special_storage_policy.cc index 7cf86cd..fd9bb3e 100644 --- a/chrome/browser/extensions/mock_extension_special_storage_policy.cc +++ b/chrome/browser/extensions/mock_extension_special_storage_policy.cc @@ -26,3 +26,7 @@ bool MockExtensionSpecialStoragePolicy::IsFileHandler( const std::string& extension_id) { return file_handlers_.find(extension_id) != file_handlers_.end(); } + +bool MockExtensionSpecialStoragePolicy::HasSessionOnlyOrigins() { + return !session_only_.empty(); +} diff --git a/chrome/browser/extensions/mock_extension_special_storage_policy.h b/chrome/browser/extensions/mock_extension_special_storage_policy.h index b4ce548..90fffbe 100644 --- a/chrome/browser/extensions/mock_extension_special_storage_policy.h +++ b/chrome/browser/extensions/mock_extension_special_storage_policy.h @@ -24,6 +24,7 @@ class MockExtensionSpecialStoragePolicy : public ExtensionSpecialStoragePolicy { virtual bool IsStorageUnlimited(const GURL& origin); virtual bool IsStorageSessionOnly(const GURL& origin); virtual bool IsFileHandler(const std::string& extension_id); + virtual bool HasSessionOnlyOrigins(); void AddProtected(const GURL& origin) { protected_.insert(origin); diff --git a/webkit/database/database_tracker.cc b/webkit/database/database_tracker.cc index 71daf48..12c6f5c 100644 --- a/webkit/database/database_tracker.cc +++ b/webkit/database/database_tracker.cc @@ -797,17 +797,33 @@ void DatabaseTracker::DeleteIncognitoDBDirectory() { file_util::Delete(incognito_db_dir, true); } -void DatabaseTracker::ClearLocalState() { +void DatabaseTracker::ClearLocalState(bool clear_all_databases) { shutting_down_ = true; + bool has_session_only_databases = + special_storage_policy_.get() && + special_storage_policy_->HasSessionOnlyOrigins(); + + // Clearning only session-only databases, and there are none. + if (!clear_all_databases && !has_session_only_databases) + return; + + if (!LazyInit()) + return; + std::vector<string16> origin_identifiers; GetAllOriginIdentifiers(&origin_identifiers); for (std::vector<string16>::iterator origin = origin_identifiers.begin(); origin != origin_identifiers.end(); ++origin) { + GURL origin_url = + webkit_database::DatabaseUtil::GetOriginFromIdentifier(*origin); + if (!clear_all_databases && + !special_storage_policy_->IsStorageSessionOnly(origin_url)) { + continue; + } if (special_storage_policy_.get() && - special_storage_policy_->IsStorageProtected( - webkit_database::DatabaseUtil::GetOriginFromIdentifier(*origin))) { + special_storage_policy_->IsStorageProtected(origin_url)) { continue; } webkit_database::OriginInfo origin_info; @@ -840,8 +856,8 @@ void DatabaseTracker::Shutdown() { } if (is_incognito_) DeleteIncognitoDBDirectory(); - else if (clear_local_state_on_exit_ && LazyInit()) - ClearLocalState(); + else + ClearLocalState(clear_local_state_on_exit_); } void DatabaseTracker::SetClearLocalStateOnExit(bool clear_local_state_on_exit) { diff --git a/webkit/database/database_tracker.h b/webkit/database/database_tracker.h index a6e793e..1acfc92 100644 --- a/webkit/database/database_tracker.h +++ b/webkit/database/database_tracker.h @@ -198,10 +198,10 @@ class DatabaseTracker // Deletes the directory that stores all DBs in incognito mode, if it exists. void DeleteIncognitoDBDirectory(); - // Deletes databases not protected by the special storage policy if - // |clear_local_state_on_exit_| is true and blocks databases from being - // created/opened. - void ClearLocalState(); + // If clear_all_databases is true, deletes all databases not protected by + // special storage policy. Otherwise deletes session-only databases. Blocks + // databases from being created/opened. + void ClearLocalState(bool clear_all_databases); bool DeleteClosedDatabase(const string16& origin_identifier, const string16& database_name); diff --git a/webkit/database/database_tracker_unittest.cc b/webkit/database/database_tracker_unittest.cc index e99f075..6fa492c 100644 --- a/webkit/database/database_tracker_unittest.cc +++ b/webkit/database/database_tracker_unittest.cc @@ -608,6 +608,85 @@ class DatabaseTracker_TestHelper_Test { EXPECT_FALSE(file_util::PathExists(origin1_db_dir)); } + static void DatabaseTrackerClearSessionOnlyDatabasesOnExit() { + int64 database_size = 0; + const string16 kOrigin1 = + DatabaseUtil::GetOriginIdentifier(GURL(kOrigin1Url)); + const string16 kOrigin2 = + DatabaseUtil::GetOriginIdentifier(GURL(kOrigin2Url)); + const string16 kDB1 = ASCIIToUTF16("db1"); + const string16 kDB2 = ASCIIToUTF16("db2"); + const string16 kDescription = ASCIIToUTF16("database_description"); + + // Initialize the tracker database. + ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + FilePath origin1_db_dir; + FilePath origin2_db_dir; + { + scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy = + new quota::MockSpecialStoragePolicy; + special_storage_policy->AddSessionOnly(GURL(kOrigin2Url)); + scoped_refptr<DatabaseTracker> tracker( + new DatabaseTracker( + temp_dir.path(), false, false /*clear_local_state_on_exit*/, + special_storage_policy, NULL, + base::MessageLoopProxy::current())); + + // Open two new databases. + tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, + &database_size); + EXPECT_EQ(0, database_size); + tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0, + &database_size); + EXPECT_EQ(0, database_size); + + // Write some data to each file. + FilePath db_file; + db_file = tracker->GetFullDBFilePath(kOrigin1, kDB1); + EXPECT_TRUE(file_util::CreateDirectory(db_file.DirName())); + EXPECT_TRUE(EnsureFileOfSize(db_file, 1)); + + db_file = tracker->GetFullDBFilePath(kOrigin2, kDB2); + EXPECT_TRUE(file_util::CreateDirectory(db_file.DirName())); + EXPECT_TRUE(EnsureFileOfSize(db_file, 2)); + + // Store the origin database directories as long as they still exist. + origin1_db_dir = tracker->GetFullDBFilePath(kOrigin1, kDB1).DirName(); + origin2_db_dir = tracker->GetFullDBFilePath(kOrigin2, kDB2).DirName(); + + tracker->DatabaseModified(kOrigin1, kDB1); + tracker->DatabaseModified(kOrigin2, kDB2); + + // Close all databases. + tracker->DatabaseClosed(kOrigin1, kDB1); + tracker->DatabaseClosed(kOrigin2, kDB2); + + tracker->Shutdown(); + } + + // At this point, the database tracker should be gone. Create a new one. + scoped_refptr<DatabaseTracker> tracker( + new DatabaseTracker(temp_dir.path(), false, false, + NULL, NULL, NULL)); + + // Get all data for all origins. + std::vector<OriginInfo> origins_info; + EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info)); + // kOrigin1 was not session-only, so it survived. kOrigin2 was session-only + // and it got deleted. + EXPECT_EQ(size_t(1), origins_info.size()); + EXPECT_EQ(kOrigin1, origins_info[0].GetOrigin()); + EXPECT_TRUE( + file_util::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1))); + EXPECT_EQ(FilePath(), tracker->GetFullDBFilePath(kOrigin2, kDB2)); + + // The origin directory of kOrigin1 remains, but the origin directory of + // kOrigin2 is deleted. + EXPECT_TRUE(file_util::PathExists(origin1_db_dir)); + EXPECT_FALSE(file_util::PathExists(origin2_db_dir)); + } + static void EmptyDatabaseNameIsValid() { const GURL kOrigin(kOrigin1Url); const string16 kOriginId = DatabaseUtil::GetOriginIdentifier(kOrigin); @@ -681,6 +760,12 @@ TEST(DatabaseTrackerTest, DatabaseTrackerClearLocalStateOnExit) { DatabaseTracker_TestHelper_Test::DatabaseTrackerClearLocalStateOnExit(); } +TEST(DatabaseTrackerTest, DatabaseTrackerClearSessionOnlyDatabasesOnExit) { + // Only works for regular mode. + DatabaseTracker_TestHelper_Test:: + DatabaseTrackerClearSessionOnlyDatabasesOnExit(); +} + TEST(DatabaseTrackerTest, EmptyDatabaseNameIsValid) { DatabaseTracker_TestHelper_Test::EmptyDatabaseNameIsValid(); } diff --git a/webkit/quota/mock_special_storage_policy.cc b/webkit/quota/mock_special_storage_policy.cc index 5787be9..c7fdb8f 100644 --- a/webkit/quota/mock_special_storage_policy.cc +++ b/webkit/quota/mock_special_storage_policy.cc @@ -29,4 +29,8 @@ bool MockSpecialStoragePolicy::IsFileHandler(const std::string& extension_id) { return file_handlers_.find(extension_id) != file_handlers_.end(); } +bool MockSpecialStoragePolicy::HasSessionOnlyOrigins() { + return !session_only_.empty(); +} + } // namespace quota diff --git a/webkit/quota/mock_special_storage_policy.h b/webkit/quota/mock_special_storage_policy.h index 7e54a6e..6f0ec13 100644 --- a/webkit/quota/mock_special_storage_policy.h +++ b/webkit/quota/mock_special_storage_policy.h @@ -21,6 +21,7 @@ class MockSpecialStoragePolicy : public quota::SpecialStoragePolicy { virtual bool IsStorageUnlimited(const GURL& origin); virtual bool IsStorageSessionOnly(const GURL& origin); virtual bool IsFileHandler(const std::string& extension_id); + virtual bool HasSessionOnlyOrigins(); void AddProtected(const GURL& origin) { protected_.insert(origin); diff --git a/webkit/quota/special_storage_policy.h b/webkit/quota/special_storage_policy.h index ed8989c..f7d80f7 100644 --- a/webkit/quota/special_storage_policy.h +++ b/webkit/quota/special_storage_policy.h @@ -46,6 +46,9 @@ class SpecialStoragePolicy // when the session ends. virtual bool IsStorageSessionOnly(const GURL& origin) = 0; + // Returns true if some origins are only allowed session-only storage. + virtual bool HasSessionOnlyOrigins() = 0; + // Adds/removes an observer, the policy does not take // ownership of the observer. Should only be called on the IO thread. void AddObserver(Observer* observer); |