// Copyright (c) 2012 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 "base/file_util.h" #include "base/files/scoped_temp_dir.h" #include "content/browser/browser_thread_impl.h" #include "content/browser/in_process_webkit/indexed_db_context_impl.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/url_constants.h" #include "content/public/test/test_browser_context.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabase.h" #include "webkit/database/database_util.h" #include "webkit/quota/mock_special_storage_policy.h" #include "webkit/quota/quota_manager.h" #include "webkit/quota/special_storage_policy.h" using webkit_database::DatabaseUtil; namespace content { class IndexedDBTest : public testing::Test { public: IndexedDBTest() : message_loop_(MessageLoop::TYPE_IO), webkit_thread_(BrowserThread::WEBKIT_DEPRECATED, &message_loop_), file_thread_(BrowserThread::FILE_USER_BLOCKING, &message_loop_), io_thread_(BrowserThread::IO, &message_loop_) { } protected: MessageLoop message_loop_; private: BrowserThreadImpl webkit_thread_; BrowserThreadImpl file_thread_; BrowserThreadImpl io_thread_; }; TEST_F(IndexedDBTest, ClearSessionOnlyDatabases) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); FilePath normal_path; FilePath session_only_path; // Create the scope which will ensure we run the destructor of the webkit // context which should trigger the clean up. { TestBrowserContext browser_context; const GURL kNormalOrigin("http://normal/"); const GURL kSessionOnlyOrigin("http://session-only/"); scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy = new quota::MockSpecialStoragePolicy; special_storage_policy->AddSessionOnly(kSessionOnlyOrigin); // Create some indexedDB paths. // With the levelDB backend, these are directories. IndexedDBContextImpl* idb_context = static_cast<IndexedDBContextImpl*>( BrowserContext::GetDefaultStoragePartition(&browser_context)-> GetIndexedDBContext()); // Override the storage policy with our own. idb_context->special_storage_policy_ = special_storage_policy; idb_context->set_data_path_for_testing(temp_dir.path()); normal_path = idb_context->GetFilePathForTesting( DatabaseUtil::GetOriginIdentifier(kNormalOrigin)); session_only_path = idb_context->GetFilePathForTesting( DatabaseUtil::GetOriginIdentifier(kSessionOnlyOrigin)); ASSERT_TRUE(file_util::CreateDirectory(normal_path)); ASSERT_TRUE(file_util::CreateDirectory(session_only_path)); message_loop_.RunUntilIdle(); } message_loop_.RunUntilIdle(); EXPECT_TRUE(file_util::DirectoryExists(normal_path)); EXPECT_FALSE(file_util::DirectoryExists(session_only_path)); } TEST_F(IndexedDBTest, SetForceKeepSessionState) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); FilePath normal_path; FilePath session_only_path; // Create the scope which will ensure we run the destructor of the webkit // context. { TestBrowserContext browser_context; const GURL kNormalOrigin("http://normal/"); const GURL kSessionOnlyOrigin("http://session-only/"); scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy = new quota::MockSpecialStoragePolicy; special_storage_policy->AddSessionOnly(kSessionOnlyOrigin); // Create some indexedDB paths. // With the levelDB backend, these are directories. IndexedDBContextImpl* idb_context = static_cast<IndexedDBContextImpl*>( BrowserContext::GetDefaultStoragePartition(&browser_context)-> GetIndexedDBContext()); // Override the storage policy with our own. idb_context->special_storage_policy_ = special_storage_policy; idb_context->set_data_path_for_testing(temp_dir.path()); // Save session state. This should bypass the destruction-time deletion. idb_context->SetForceKeepSessionState(); normal_path = idb_context->GetFilePathForTesting( DatabaseUtil::GetOriginIdentifier(kNormalOrigin)); session_only_path = idb_context->GetFilePathForTesting( DatabaseUtil::GetOriginIdentifier(kSessionOnlyOrigin)); ASSERT_TRUE(file_util::CreateDirectory(normal_path)); ASSERT_TRUE(file_util::CreateDirectory(session_only_path)); message_loop_.RunUntilIdle(); } // Make sure we wait until the destructor has run. message_loop_.RunUntilIdle(); // No data was cleared because of SetForceKeepSessionState. EXPECT_TRUE(file_util::DirectoryExists(normal_path)); EXPECT_TRUE(file_util::DirectoryExists(session_only_path)); } class MockWebIDBDatabase : public WebKit::WebIDBDatabase { public: MockWebIDBDatabase(bool expect_force_close) : expect_force_close_(expect_force_close), force_close_called_(false) {} ~MockWebIDBDatabase() { EXPECT_TRUE(force_close_called_ == expect_force_close_); } virtual void forceClose() { ASSERT_TRUE(expect_force_close_); force_close_called_ = true; } private: bool expect_force_close_; bool force_close_called_; }; TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); FilePath test_path; // Create the scope which will ensure we run the destructor of the webkit // context. { TestBrowserContext browser_context; const GURL kTestOrigin("http://test/"); IndexedDBContextImpl* idb_context = static_cast<IndexedDBContextImpl*>( BrowserContext::GetDefaultStoragePartition(&browser_context)-> GetIndexedDBContext()); idb_context->quota_manager_proxy_ = NULL; idb_context->set_data_path_for_testing(temp_dir.path()); test_path = idb_context->GetFilePathForTesting( DatabaseUtil::GetOriginIdentifier(kTestOrigin)); ASSERT_TRUE(file_util::CreateDirectory(test_path)); const bool kExpectForceClose = true; MockWebIDBDatabase connection1(kExpectForceClose); idb_context->ConnectionOpened(kTestOrigin, &connection1); MockWebIDBDatabase connection2(!kExpectForceClose); idb_context->ConnectionOpened(kTestOrigin, &connection2); idb_context->ConnectionClosed(kTestOrigin, &connection2); idb_context->DeleteForOrigin(kTestOrigin); message_loop_.RunUntilIdle(); } // Make sure we wait until the destructor has run. message_loop_.RunUntilIdle(); EXPECT_FALSE(file_util::DirectoryExists(test_path)); } } // namespace content