Index: content/browser/storage_partition_impl_unittest.cc |
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc |
index 6aa0c1b0877ed9aa8e814c0f33b6dc14be32f22d..30b24b2afba2bd17298dfae6abe862df1bda43c2 100644 |
--- a/content/browser/storage_partition_impl_unittest.cc |
+++ b/content/browser/storage_partition_impl_unittest.cc |
@@ -27,6 +27,10 @@ |
#include "net/cookies/cookie_store.h" |
#include "net/url_request/url_request_context.h" |
#include "net/url_request/url_request_context_getter.h" |
+#include "storage/browser/fileapi/async_file_util.h" |
+#include "storage/browser/fileapi/file_system_context.h" |
+#include "storage/browser/fileapi/file_system_operation_context.h" |
+#include "storage/browser/fileapi/isolated_context.h" |
#include "storage/browser/quota/quota_manager.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -44,6 +48,10 @@ const char kTestOrigin2[] = "http://host2:1/"; |
const char kTestOrigin3[] = "http://host3:1/"; |
const char kTestOriginDevTools[] = "chrome-devtools://abcdefghijklmnopqrstuvw/"; |
+const char kPluginPrivateRootName[] = "pluginprivate"; |
+const char kWidevineCdmPluginId[] = "application_x-ppapi-widevine-cdm"; |
+const char kClearKeyCdmPluginId[] = "application_x-ppapi-clearkey-cdm"; |
+ |
const GURL kOrigin1(kTestOrigin1); |
const GURL kOrigin2(kTestOrigin2); |
const GURL kOrigin3(kTestOrigin3); |
@@ -231,6 +239,144 @@ class RemoveLocalStorageTester { |
DISALLOW_COPY_AND_ASSIGN(RemoveLocalStorageTester); |
}; |
+class RemovePluginPrivateDataTester { |
+ public: |
+ explicit RemovePluginPrivateDataTester( |
+ storage::FileSystemContext* filesystem_context) |
+ : filesystem_context_(filesystem_context) {} |
+ |
+ // Add some files to the PluginPrivateFileSystem. They are created as follows: |
+ // kOrigin1 - ClearKey - 1 file - timestamp 10 days ago |
+ // kOrigin2 - Widevine - 2 files - timestamps now and 60 days ago |
+ void AddPluginPrivateTestData() { |
+ base::Time now = base::Time::Now(); |
+ base::Time ten_days_ago = now - base::TimeDelta::FromDays(10); |
+ base::Time sixty_days_ago = now - base::TimeDelta::FromDays(60); |
+ |
+ // Create a PluginPrivateFileSystem for ClearKey and add a single file |
+ // with a timestamp of 1 day ago. |
+ std::string clearkey_fsid = |
+ CreateFileSystem(kClearKeyCdmPluginId, kOrigin1); |
+ storage::FileSystemURL clearkey_file = |
+ CreateFile(kOrigin1, clearkey_fsid, "foo"); |
+ SetFileTimestamp(clearkey_file, ten_days_ago); |
+ |
+ // Create a second PluginPrivateFileSystem for Widevine and add two files |
+ // with different times. |
+ std::string widevine_fsid = |
+ CreateFileSystem(kWidevineCdmPluginId, kOrigin2); |
+ storage::FileSystemURL widevine_file1 = |
+ CreateFile(kOrigin2, widevine_fsid, "bar1"); |
+ storage::FileSystemURL widevine_file2 = |
+ CreateFile(kOrigin2, widevine_fsid, "bar2"); |
+ SetFileTimestamp(widevine_file1, now); |
+ SetFileTimestamp(widevine_file2, sixty_days_ago); |
+ } |
+ |
+ // Returns true, if the given origin exists in a PluginPrivateFileSystem. |
+ bool DataExistsForOrigin(const GURL& origin) { |
+ storage::FileSystemBackend* backend = |
+ filesystem_context_->GetFileSystemBackend( |
+ storage::kFileSystemTypePluginPrivate); |
+ storage::FileSystemQuotaUtil* quota_util = backend->GetQuotaUtil(); |
+ |
+ // Determine the set of origins used. |
+ std::set<GURL> origins; |
+ quota_util->GetOriginsForTypeOnFileTaskRunner( |
+ storage::kFileSystemTypePluginPrivate, &origins); |
+ return origins.find(origin) != origins.end(); |
+ } |
+ |
+ private: |
+ // Creates a PluginPrivateFileSystem for the |plugin_name| and |origin| |
+ // provided. Returns the file system ID for the created |
+ // PluginPrivateFileSystem. |
+ std::string CreateFileSystem(const std::string& plugin_name, |
+ const GURL& origin) { |
+ AwaitCompletionHelper await_completion; |
+ std::string fsid = storage::IsolatedContext::GetInstance() |
+ ->RegisterFileSystemForVirtualPath( |
+ storage::kFileSystemTypePluginPrivate, |
+ kPluginPrivateRootName, base::FilePath()); |
+ EXPECT_TRUE(storage::ValidateIsolatedFileSystemId(fsid)); |
+ filesystem_context_->OpenPluginPrivateFileSystem( |
+ origin, storage::kFileSystemTypePluginPrivate, fsid, plugin_name, |
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, |
+ base::Bind(&RemovePluginPrivateDataTester::OnFileSystemOpened, |
+ base::Unretained(this), &await_completion)); |
+ await_completion.BlockUntilNotified(); |
+ return fsid; |
+ } |
+ |
+ // Creates a file named |file_name| in the PluginPrivateFileSystem identified |
+ // by |origin| and |fsid|. Returns the URL for the created file. The file |
+ // musty not already exist or the test will fail. |
+ storage::FileSystemURL CreateFile(const GURL& origin, |
+ const std::string& fsid, |
+ const std::string& file_name) { |
+ AwaitCompletionHelper await_completion; |
+ std::string root = storage::GetIsolatedFileSystemRootURIString( |
+ origin, fsid, kPluginPrivateRootName); |
+ storage::FileSystemURL file_url = |
+ filesystem_context_->CrackURL(GURL(root + file_name)); |
+ storage::AsyncFileUtil* file_util = filesystem_context_->GetAsyncFileUtil( |
+ storage::kFileSystemTypePluginPrivate); |
+ std::unique_ptr<storage::FileSystemOperationContext> operation_context = |
+ base::WrapUnique( |
+ new storage::FileSystemOperationContext(filesystem_context_)); |
+ operation_context->set_allowed_bytes_growth( |
+ storage::QuotaManager::kNoLimit); |
+ file_util->EnsureFileExists( |
+ std::move(operation_context), file_url, |
+ base::Bind(&RemovePluginPrivateDataTester::OnFileCreated, |
+ base::Unretained(this), &await_completion)); |
+ await_completion.BlockUntilNotified(); |
+ return file_url; |
+ } |
+ |
+ // Sets the last_access_time and last_modified_time to |time_stamp| on the |
+ // file specified by |file_url|. The file must already exist. |
+ void SetFileTimestamp(const storage::FileSystemURL& file_url, |
+ const base::Time& time_stamp) { |
+ AwaitCompletionHelper await_completion; |
+ storage::AsyncFileUtil* file_util = filesystem_context_->GetAsyncFileUtil( |
+ storage::kFileSystemTypePluginPrivate); |
+ std::unique_ptr<storage::FileSystemOperationContext> operation_context = |
+ base::WrapUnique( |
+ new storage::FileSystemOperationContext(filesystem_context_)); |
+ file_util->Touch(std::move(operation_context), file_url, time_stamp, |
+ time_stamp, |
+ base::Bind(&RemovePluginPrivateDataTester::OnFileTouched, |
+ base::Unretained(this), &await_completion)); |
+ await_completion.BlockUntilNotified(); |
+ } |
+ |
+ void OnFileSystemOpened(AwaitCompletionHelper* await_completion, |
+ base::File::Error result) { |
+ EXPECT_EQ(base::File::FILE_OK, result) << base::File::ErrorToString(result); |
+ await_completion->Notify(); |
+ } |
+ |
+ void OnFileCreated(AwaitCompletionHelper* await_completion, |
+ base::File::Error result, |
+ bool created) { |
+ EXPECT_EQ(base::File::FILE_OK, result) << base::File::ErrorToString(result); |
+ EXPECT_TRUE(created); |
+ await_completion->Notify(); |
+ } |
+ |
+ void OnFileTouched(AwaitCompletionHelper* await_completion, |
+ base::File::Error result) { |
+ EXPECT_EQ(base::File::FILE_OK, result) << base::File::ErrorToString(result); |
+ await_completion->Notify(); |
+ } |
+ |
+ // We don't own this pointer. |
+ storage::FileSystemContext* filesystem_context_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(RemovePluginPrivateDataTester); |
+}; |
+ |
bool IsWebSafeSchemeForTest(const std::string& scheme) { |
return scheme == "http"; |
} |
@@ -344,6 +490,18 @@ void ClearData(content::StoragePartition* partition, |
time, time, run_loop->QuitClosure()); |
} |
+void ClearPluginPrivateData(content::StoragePartition* partition, |
+ const GURL& storage_origin, |
+ const base::Time delete_begin, |
+ const base::Time delete_end, |
+ base::RunLoop* run_loop) { |
+ partition->ClearData( |
+ StoragePartitionImpl::REMOVE_DATA_MASK_PLUGIN_PRIVATE_DATA, |
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, storage_origin, |
+ StoragePartition::OriginMatcherFunction(), delete_begin, delete_end, |
+ run_loop->QuitClosure()); |
+} |
+ |
} // namespace |
class StoragePartitionImplTest : public testing::Test { |
@@ -975,6 +1133,68 @@ TEST_F(StoragePartitionImplTest, RemoveLocalStorageForLastWeek) { |
EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin3)); |
} |
+TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataForever) { |
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( |
+ BrowserContext::GetDefaultStoragePartition(browser_context())); |
+ |
+ RemovePluginPrivateDataTester tester(partition->GetFileSystemContext()); |
+ tester.AddPluginPrivateTestData(); |
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1)); |
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2)); |
+ |
+ base::RunLoop run_loop; |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, base::Bind(&ClearPluginPrivateData, partition, GURL(), |
+ base::Time(), base::Time::Max(), &run_loop)); |
+ run_loop.Run(); |
+ |
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin1)); |
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin2)); |
+} |
+ |
+TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataLastWeek) { |
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( |
+ BrowserContext::GetDefaultStoragePartition(browser_context())); |
+ base::Time a_week_ago = base::Time::Now() - base::TimeDelta::FromDays(7); |
+ |
+ RemovePluginPrivateDataTester tester(partition->GetFileSystemContext()); |
+ tester.AddPluginPrivateTestData(); |
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1)); |
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2)); |
+ |
+ base::RunLoop run_loop; |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, base::Bind(&ClearPluginPrivateData, partition, GURL(), |
+ a_week_ago, base::Time::Max(), &run_loop)); |
+ run_loop.Run(); |
+ |
+ // Origin1 has 1 file from 10 days ago, so it should remain around. |
+ // Origin2 has a current file, so it should be removed (even though the |
+ // second file is much older). |
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1)); |
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin2)); |
+} |
+ |
+TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataForOrigin) { |
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( |
+ BrowserContext::GetDefaultStoragePartition(browser_context())); |
+ |
+ RemovePluginPrivateDataTester tester(partition->GetFileSystemContext()); |
+ tester.AddPluginPrivateTestData(); |
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1)); |
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2)); |
+ |
+ base::RunLoop run_loop; |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, base::Bind(&ClearPluginPrivateData, partition, kOrigin1, |
+ base::Time(), base::Time::Max(), &run_loop)); |
+ run_loop.Run(); |
+ |
+ // Only Origin1 should be deleted. |
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin1)); |
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2)); |
+} |
+ |
TEST(StoragePartitionImplStaticTest, CreatePredicateForHostCookies) { |
GURL url("http://www.example.com/"); |
GURL url2("https://www.example.com/"); |