| Index: content/browser/indexed_db/indexed_db_factory_unittest.cc
|
| diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
|
| index 374143ad3b935d4c7102bb4ac0e1398f883329ad..1c872813917b94c3eab85a3507a5d29feb2ff4f3 100644
|
| --- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
|
| +++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
|
| @@ -14,7 +14,7 @@
|
| #include "base/run_loop.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/test/test_simple_task_runner.h"
|
| -#include "base/threading/thread_task_runner_handle.h"
|
| +#include "base/threading/sequenced_task_runner_handle.h"
|
| #include "content/browser/indexed_db/indexed_db_connection.h"
|
| #include "content/browser/indexed_db/indexed_db_context_impl.h"
|
| #include "content/browser/indexed_db/indexed_db_data_format_version.h"
|
| @@ -22,6 +22,7 @@
|
| #include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
|
| #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
|
| #include "content/public/test/test_browser_thread_bundle.h"
|
| +#include "content/public/test/test_utils.h"
|
| #include "storage/browser/test/mock_quota_manager_proxy.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
|
| @@ -72,14 +73,15 @@ class MockIDBFactory : public IndexedDBFactoryImpl {
|
|
|
| class IndexedDBFactoryTest : public testing::Test {
|
| public:
|
| + IndexedDBFactoryTest()
|
| + : quota_manager_proxy_(
|
| + base::MakeRefCounted<MockQuotaManagerProxy>(nullptr, nullptr)) {}
|
| +
|
| void SetUp() override {
|
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
|
| - task_runner_ = new base::TestSimpleTaskRunner();
|
| - quota_manager_proxy_ = new MockQuotaManagerProxy(nullptr, nullptr);
|
| - context_ = new IndexedDBContextImpl(
|
| + context_ = base::MakeRefCounted<IndexedDBContextImpl>(
|
| temp_dir_.GetPath(), nullptr /* special_storage_policy */,
|
| - quota_manager_proxy_.get(), task_runner_.get());
|
| - idb_factory_ = new MockIDBFactory(context_.get());
|
| + quota_manager_proxy_.get());
|
| }
|
|
|
| void TearDown() override {
|
| @@ -87,127 +89,164 @@ class IndexedDBFactoryTest : public testing::Test {
|
| }
|
|
|
| protected:
|
| - IndexedDBFactoryTest() {}
|
| - MockIDBFactory* factory() const { return idb_factory_.get(); }
|
| - void clear_factory() { idb_factory_ = nullptr; }
|
| IndexedDBContextImpl* context() const { return context_.get(); }
|
|
|
| private:
|
| + TestBrowserThreadBundle thread_bundle_;
|
| +
|
| base::ScopedTempDir temp_dir_;
|
| - scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
|
| - scoped_refptr<IndexedDBContextImpl> context_;
|
| - scoped_refptr<MockIDBFactory> idb_factory_;
|
| scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
|
| - TestBrowserThreadBundle thread_bundle_;
|
| + scoped_refptr<IndexedDBContextImpl> context_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryTest);
|
| };
|
|
|
| TEST_F(IndexedDBFactoryTest, BackingStoreLifetime) {
|
| - const Origin origin1(GURL("http://localhost:81"));
|
| - const Origin origin2(GURL("http://localhost:82"));
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context) {
|
| + scoped_refptr<MockIDBFactory> factory =
|
| + base::MakeRefCounted<MockIDBFactory>(context);
|
| +
|
| + const Origin origin1(GURL("http://localhost:81"));
|
| + const Origin origin2(GURL("http://localhost:82"));
|
|
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| - scoped_refptr<IndexedDBBackingStore> disk_store1 =
|
| - factory()->TestOpenBackingStore(origin1, temp_directory.GetPath());
|
| + scoped_refptr<IndexedDBBackingStore> disk_store1 =
|
| + factory->TestOpenBackingStore(origin1, context->data_path());
|
|
|
| - scoped_refptr<IndexedDBBackingStore> disk_store2 =
|
| - factory()->TestOpenBackingStore(origin1, temp_directory.GetPath());
|
| - EXPECT_EQ(disk_store1.get(), disk_store2.get());
|
| + scoped_refptr<IndexedDBBackingStore> disk_store2 =
|
| + factory->TestOpenBackingStore(origin1, context->data_path());
|
| + EXPECT_EQ(disk_store1.get(), disk_store2.get());
|
|
|
| - scoped_refptr<IndexedDBBackingStore> disk_store3 =
|
| - factory()->TestOpenBackingStore(origin2, temp_directory.GetPath());
|
| + scoped_refptr<IndexedDBBackingStore> disk_store3 =
|
| + factory->TestOpenBackingStore(origin2, context->data_path());
|
|
|
| - factory()->TestCloseBackingStore(disk_store1.get());
|
| - factory()->TestCloseBackingStore(disk_store3.get());
|
| + factory->TestCloseBackingStore(disk_store1.get());
|
| + factory->TestCloseBackingStore(disk_store3.get());
|
|
|
| - EXPECT_FALSE(disk_store1->HasOneRef());
|
| - EXPECT_FALSE(disk_store2->HasOneRef());
|
| - EXPECT_TRUE(disk_store3->HasOneRef());
|
| + EXPECT_FALSE(disk_store1->HasOneRef());
|
| + EXPECT_FALSE(disk_store2->HasOneRef());
|
| + EXPECT_TRUE(disk_store3->HasOneRef());
|
|
|
| - disk_store2 = nullptr;
|
| - EXPECT_TRUE(disk_store1->HasOneRef());
|
| + disk_store2 = nullptr;
|
| + EXPECT_TRUE(disk_store1->HasOneRef());
|
| + },
|
| + base::Unretained(context())));
|
| +
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| TEST_F(IndexedDBFactoryTest, BackingStoreLazyClose) {
|
| - const Origin origin(GURL("http://localhost:81"));
|
| -
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| - scoped_refptr<IndexedDBBackingStore> store =
|
| - factory()->TestOpenBackingStore(origin, temp_directory.GetPath());
|
| -
|
| - // Give up the local refptr so that the factory has the only
|
| - // outstanding reference.
|
| - IndexedDBBackingStore* store_ptr = store.get();
|
| - store = nullptr;
|
| - EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
|
| - factory()->TestReleaseBackingStore(store_ptr, false);
|
| - EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
|
| -
|
| - factory()->TestOpenBackingStore(origin, temp_directory.GetPath());
|
| - EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
|
| - factory()->TestReleaseBackingStore(store_ptr, false);
|
| - EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
|
| -
|
| - // Take back a ref ptr and ensure that the actual close
|
| - // stops a running timer.
|
| - store = store_ptr;
|
| - factory()->TestCloseBackingStore(store_ptr);
|
| - EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context) {
|
| +
|
| + scoped_refptr<MockIDBFactory> factory =
|
| + base::MakeRefCounted<MockIDBFactory>(context);
|
| +
|
| + const Origin origin(GURL("http://localhost:81"));
|
| +
|
| + scoped_refptr<IndexedDBBackingStore> store =
|
| + factory->TestOpenBackingStore(origin, context->data_path());
|
| +
|
| + // Give up the local refptr so that the factory has the only
|
| + // outstanding reference.
|
| + IndexedDBBackingStore* store_ptr = store.get();
|
| + store = nullptr;
|
| + EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
|
| + factory->TestReleaseBackingStore(store_ptr, false);
|
| + EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
|
| +
|
| + factory->TestOpenBackingStore(origin, context->data_path());
|
| + EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
|
| + factory->TestReleaseBackingStore(store_ptr, false);
|
| + EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
|
| +
|
| + // Take back a ref ptr and ensure that the actual close
|
| + // stops a running timer.
|
| + store = store_ptr;
|
| + factory->TestCloseBackingStore(store_ptr);
|
| + EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
|
| + },
|
| + base::Unretained(context())));
|
| +
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| TEST_F(IndexedDBFactoryTest, MemoryBackingStoreLifetime) {
|
| - const Origin origin1(GURL("http://localhost:81"));
|
| - const Origin origin2(GURL("http://localhost:82"));
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context) {
|
| +
|
| + scoped_refptr<MockIDBFactory> factory =
|
| + base::MakeRefCounted<MockIDBFactory>(context);
|
|
|
| - scoped_refptr<IndexedDBBackingStore> mem_store1 =
|
| - factory()->TestOpenBackingStore(origin1, base::FilePath());
|
| + const Origin origin1(GURL("http://localhost:81"));
|
| + const Origin origin2(GURL("http://localhost:82"));
|
|
|
| - scoped_refptr<IndexedDBBackingStore> mem_store2 =
|
| - factory()->TestOpenBackingStore(origin1, base::FilePath());
|
| - EXPECT_EQ(mem_store1.get(), mem_store2.get());
|
| + scoped_refptr<IndexedDBBackingStore> mem_store1 =
|
| + factory->TestOpenBackingStore(origin1, base::FilePath());
|
|
|
| - scoped_refptr<IndexedDBBackingStore> mem_store3 =
|
| - factory()->TestOpenBackingStore(origin2, base::FilePath());
|
| + scoped_refptr<IndexedDBBackingStore> mem_store2 =
|
| + factory->TestOpenBackingStore(origin1, base::FilePath());
|
| + EXPECT_EQ(mem_store1.get(), mem_store2.get());
|
|
|
| - factory()->TestCloseBackingStore(mem_store1.get());
|
| - factory()->TestCloseBackingStore(mem_store3.get());
|
| + scoped_refptr<IndexedDBBackingStore> mem_store3 =
|
| + factory->TestOpenBackingStore(origin2, base::FilePath());
|
|
|
| - EXPECT_FALSE(mem_store1->HasOneRef());
|
| - EXPECT_FALSE(mem_store2->HasOneRef());
|
| - EXPECT_FALSE(mem_store3->HasOneRef());
|
| + factory->TestCloseBackingStore(mem_store1.get());
|
| + factory->TestCloseBackingStore(mem_store3.get());
|
|
|
| - clear_factory();
|
| - EXPECT_FALSE(mem_store1->HasOneRef()); // mem_store1 and 2
|
| - EXPECT_FALSE(mem_store2->HasOneRef()); // mem_store1 and 2
|
| - EXPECT_TRUE(mem_store3->HasOneRef());
|
| + EXPECT_FALSE(mem_store1->HasOneRef());
|
| + EXPECT_FALSE(mem_store2->HasOneRef());
|
| + EXPECT_FALSE(mem_store3->HasOneRef());
|
|
|
| - mem_store2 = nullptr;
|
| - EXPECT_TRUE(mem_store1->HasOneRef());
|
| + factory = nullptr;
|
| + EXPECT_FALSE(mem_store1->HasOneRef()); // mem_store1 and 2
|
| + EXPECT_FALSE(mem_store2->HasOneRef()); // mem_store1 and 2
|
| + EXPECT_TRUE(mem_store3->HasOneRef());
|
| +
|
| + mem_store2 = nullptr;
|
| + EXPECT_TRUE(mem_store1->HasOneRef());
|
| + },
|
| + base::Unretained(context())));
|
| +
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| TEST_F(IndexedDBFactoryTest, RejectLongOrigins) {
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| - const base::FilePath base_path = temp_directory.GetPath();
|
| -
|
| - int limit = base::GetMaximumPathComponentLength(base_path);
|
| - EXPECT_GT(limit, 0);
|
| -
|
| - std::string origin(limit + 1, 'x');
|
| - Origin too_long_origin(GURL("http://" + origin + ":81/"));
|
| - scoped_refptr<IndexedDBBackingStore> diskStore1 =
|
| - factory()->TestOpenBackingStore(too_long_origin, base_path);
|
| - EXPECT_FALSE(diskStore1.get());
|
| -
|
| - Origin ok_origin(GURL("http://someorigin.com:82/"));
|
| - scoped_refptr<IndexedDBBackingStore> diskStore2 =
|
| - factory()->TestOpenBackingStore(ok_origin, base_path);
|
| - EXPECT_TRUE(diskStore2.get());
|
| - // We need a manual close or Windows can't delete the temp directory.
|
| - factory()->TestCloseBackingStore(diskStore2.get());
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context) {
|
| + base::FilePath temp_dir = context->data_path().DirName();
|
| + int limit = base::GetMaximumPathComponentLength(temp_dir);
|
| + EXPECT_GT(limit, 0);
|
| +
|
| + scoped_refptr<MockIDBFactory> factory =
|
| + base::MakeRefCounted<MockIDBFactory>(context);
|
| +
|
| + std::string origin(limit + 1, 'x');
|
| + Origin too_long_origin(GURL("http://" + origin + ":81/"));
|
| + scoped_refptr<IndexedDBBackingStore> diskStore1 =
|
| + factory->TestOpenBackingStore(too_long_origin,
|
| + context->data_path());
|
| + EXPECT_FALSE(diskStore1.get());
|
| +
|
| + Origin ok_origin(GURL("http://someorigin.com:82/"));
|
| + scoped_refptr<IndexedDBBackingStore> diskStore2 =
|
| + factory->TestOpenBackingStore(ok_origin, context->data_path());
|
| + EXPECT_TRUE(diskStore2.get());
|
| + // We need a manual close or Windows can't delete the temp
|
| + // directory.
|
| + factory->TestCloseBackingStore(diskStore2.get());
|
| + },
|
| + base::Unretained(context())));
|
| +
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| class DiskFullFactory : public IndexedDBFactoryImpl {
|
| @@ -238,7 +277,7 @@ class LookingForQuotaErrorMockCallbacks : public IndexedDBCallbacks {
|
| : IndexedDBCallbacks(nullptr,
|
| url::Origin(),
|
| nullptr,
|
| - base::ThreadTaskRunnerHandle::Get()),
|
| + base::SequencedTaskRunnerHandle::Get()),
|
| error_called_(false) {}
|
| void OnError(const IndexedDBDatabaseError& error) override {
|
| error_called_ = true;
|
| @@ -254,177 +293,232 @@ class LookingForQuotaErrorMockCallbacks : public IndexedDBCallbacks {
|
| };
|
|
|
| TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) {
|
| - const Origin origin(GURL("http://localhost:81"));
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| -
|
| - scoped_refptr<DiskFullFactory> factory = new DiskFullFactory(context());
|
| scoped_refptr<LookingForQuotaErrorMockCallbacks> callbacks =
|
| - new LookingForQuotaErrorMockCallbacks;
|
| + base::MakeRefCounted<LookingForQuotaErrorMockCallbacks>();
|
| scoped_refptr<IndexedDBDatabaseCallbacks> dummy_database_callbacks =
|
| - new IndexedDBDatabaseCallbacks(nullptr, nullptr);
|
| - const base::string16 name(ASCIIToUTF16("name"));
|
| - std::unique_ptr<IndexedDBPendingConnection> connection(
|
| - base::MakeUnique<IndexedDBPendingConnection>(
|
| - callbacks, dummy_database_callbacks, 0 /* child_process_id */,
|
| - 2 /* transaction_id */, 1 /* version */));
|
| - factory->Open(name, std::move(connection), nullptr /* request_context */,
|
| - origin, temp_directory.GetPath());
|
| - EXPECT_TRUE(callbacks->error_called());
|
| + base::MakeRefCounted<IndexedDBDatabaseCallbacks>(nullptr, nullptr);
|
| +
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context,
|
| + scoped_refptr<LookingForQuotaErrorMockCallbacks> callbacks,
|
| + scoped_refptr<IndexedDBDatabaseCallbacks>
|
| + dummy_database_callbacks) {
|
| +
|
| + const Origin origin(GURL("http://localhost:81"));
|
| + scoped_refptr<DiskFullFactory> factory =
|
| + base::MakeRefCounted<DiskFullFactory>(context);
|
| + const base::string16 name(ASCIIToUTF16("name"));
|
| + std::unique_ptr<IndexedDBPendingConnection> connection(
|
| + base::MakeUnique<IndexedDBPendingConnection>(
|
| + callbacks, dummy_database_callbacks,
|
| + 0 /* child_process_id */, 2 /* transaction_id */,
|
| + 1 /* version */));
|
| + factory->Open(name, std::move(connection),
|
| + nullptr /* request_context */, origin,
|
| + context->data_path());
|
| + EXPECT_TRUE(callbacks->error_called());
|
| + },
|
| + base::Unretained(context()), std::move(callbacks),
|
| + std::move(dummy_database_callbacks)));
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| TEST_F(IndexedDBFactoryTest, BackingStoreReleasedOnForcedClose) {
|
| - const Origin origin(GURL("http://localhost:81"));
|
| -
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| -
|
| - scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks());
|
| - scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
|
| - new MockIndexedDBDatabaseCallbacks());
|
| - const int64_t transaction_id = 1;
|
| - std::unique_ptr<IndexedDBPendingConnection> connection(
|
| - base::MakeUnique<IndexedDBPendingConnection>(
|
| - callbacks, db_callbacks, 0 /* child_process_id */, transaction_id,
|
| - IndexedDBDatabaseMetadata::DEFAULT_VERSION));
|
| - factory()->Open(ASCIIToUTF16("db"), std::move(connection),
|
| - nullptr /* request_context */, origin,
|
| - temp_directory.GetPath());
|
| -
|
| - EXPECT_TRUE(callbacks->connection());
|
| -
|
| - EXPECT_TRUE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_FALSE(factory()->IsBackingStorePendingClose(origin));
|
| -
|
| - callbacks->connection()->ForceClose();
|
| -
|
| - EXPECT_FALSE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_FALSE(factory()->IsBackingStorePendingClose(origin));
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context,
|
| + scoped_refptr<MockIndexedDBCallbacks> callbacks,
|
| + scoped_refptr<IndexedDBDatabaseCallbacks> db_callbacks) {
|
| +
|
| + scoped_refptr<MockIDBFactory> factory =
|
| + base::MakeRefCounted<MockIDBFactory>(context);
|
| +
|
| + const Origin origin(GURL("http://localhost:81"));
|
| + const int64_t transaction_id = 1;
|
| + std::unique_ptr<IndexedDBPendingConnection> connection(
|
| + base::MakeUnique<IndexedDBPendingConnection>(
|
| + callbacks, db_callbacks, 0 /* child_process_id */,
|
| + transaction_id,
|
| + IndexedDBDatabaseMetadata::DEFAULT_VERSION));
|
| + factory->Open(ASCIIToUTF16("db"), std::move(connection),
|
| + nullptr /* request_context */, origin,
|
| + context->data_path());
|
| +
|
| + EXPECT_TRUE(callbacks->connection());
|
| +
|
| + EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
|
| +
|
| + callbacks->connection()->ForceClose();
|
| +
|
| + EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
|
| + },
|
| + base::Unretained(context()),
|
| + base::MakeRefCounted<MockIndexedDBCallbacks>(),
|
| + base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>()));
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| TEST_F(IndexedDBFactoryTest, BackingStoreReleaseDelayedOnClose) {
|
| - const Origin origin(GURL("http://localhost:81"));
|
| -
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| -
|
| - scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks());
|
| - scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
|
| - new MockIndexedDBDatabaseCallbacks());
|
| - const int64_t transaction_id = 1;
|
| - std::unique_ptr<IndexedDBPendingConnection> connection(
|
| - base::MakeUnique<IndexedDBPendingConnection>(
|
| - callbacks, db_callbacks, 0 /* child_process_id */, transaction_id,
|
| - IndexedDBDatabaseMetadata::DEFAULT_VERSION));
|
| - factory()->Open(ASCIIToUTF16("db"), std::move(connection),
|
| - nullptr /* request_context */, origin,
|
| - temp_directory.GetPath());
|
| -
|
| - EXPECT_TRUE(callbacks->connection());
|
| - IndexedDBBackingStore* store =
|
| - callbacks->connection()->database()->backing_store();
|
| - EXPECT_FALSE(store->HasOneRef()); // Factory and database.
|
| -
|
| - EXPECT_TRUE(factory()->IsBackingStoreOpen(origin));
|
| - callbacks->connection()->Close();
|
| - EXPECT_TRUE(store->HasOneRef()); // Factory.
|
| - EXPECT_TRUE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_TRUE(factory()->IsBackingStorePendingClose(origin));
|
| - EXPECT_TRUE(store->close_timer()->IsRunning());
|
| -
|
| - // Take a ref so it won't be destroyed out from under the test.
|
| - scoped_refptr<IndexedDBBackingStore> store_ref = store;
|
| - // Now simulate shutdown, which should stop the timer.
|
| - factory()->ContextDestroyed();
|
| - EXPECT_TRUE(store->HasOneRef()); // Local.
|
| - EXPECT_FALSE(store->close_timer()->IsRunning());
|
| - EXPECT_FALSE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_FALSE(factory()->IsBackingStorePendingClose(origin));
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context,
|
| + scoped_refptr<MockIndexedDBCallbacks> callbacks,
|
| + scoped_refptr<IndexedDBDatabaseCallbacks> db_callbacks) {
|
| +
|
| + scoped_refptr<MockIDBFactory> factory =
|
| + base::MakeRefCounted<MockIDBFactory>(context);
|
| +
|
| + const Origin origin(GURL("http://localhost:81"));
|
| + const int64_t transaction_id = 1;
|
| + std::unique_ptr<IndexedDBPendingConnection> connection(
|
| + base::MakeUnique<IndexedDBPendingConnection>(
|
| + callbacks, db_callbacks, 0 /* child_process_id */,
|
| + transaction_id,
|
| + IndexedDBDatabaseMetadata::DEFAULT_VERSION));
|
| + factory->Open(ASCIIToUTF16("db"), std::move(connection),
|
| + nullptr /* request_context */, origin,
|
| + context->data_path());
|
| +
|
| + EXPECT_TRUE(callbacks->connection());
|
| + IndexedDBBackingStore* store =
|
| + callbacks->connection()->database()->backing_store();
|
| + EXPECT_FALSE(store->HasOneRef()); // Factory and database.
|
| +
|
| + EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
|
| + callbacks->connection()->Close();
|
| + EXPECT_TRUE(store->HasOneRef()); // Factory.
|
| + EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
|
| + EXPECT_TRUE(store->close_timer()->IsRunning());
|
| +
|
| + // Take a ref so it won't be destroyed out from under the test.
|
| + scoped_refptr<IndexedDBBackingStore> store_ref = store;
|
| + // Now simulate shutdown, which should stop the timer.
|
| + factory->ContextDestroyed();
|
| + EXPECT_TRUE(store->HasOneRef()); // Local.
|
| + EXPECT_FALSE(store->close_timer()->IsRunning());
|
| + EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
|
| + },
|
| + base::Unretained(context()),
|
| + base::MakeRefCounted<MockIndexedDBCallbacks>(),
|
| + base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>()));
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| TEST_F(IndexedDBFactoryTest, DeleteDatabaseClosesBackingStore) {
|
| - const Origin origin(GURL("http://localhost:81"));
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context,
|
| + scoped_refptr<MockIndexedDBCallbacks> callbacks) {
|
| +
|
| + scoped_refptr<MockIDBFactory> factory =
|
| + base::MakeRefCounted<MockIDBFactory>(context);
|
|
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| + const Origin origin(GURL("http://localhost:81"));
|
| + EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
|
|
|
| - EXPECT_FALSE(factory()->IsBackingStoreOpen(origin));
|
| + factory->DeleteDatabase(
|
| + ASCIIToUTF16("db"), nullptr /* request_context */, callbacks,
|
| + origin, context->data_path(), false /* force_close */);
|
|
|
| - const bool expect_connection = false;
|
| - scoped_refptr<MockIndexedDBCallbacks> callbacks(
|
| - new MockIndexedDBCallbacks(expect_connection));
|
| - factory()->DeleteDatabase(ASCIIToUTF16("db"), nullptr /* request_context */,
|
| - callbacks, origin, temp_directory.GetPath(),
|
| - false /* force_close */);
|
| + EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
|
|
|
| - EXPECT_TRUE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_TRUE(factory()->IsBackingStorePendingClose(origin));
|
| + // Now simulate shutdown, which should stop the timer.
|
| + factory->ContextDestroyed();
|
|
|
| - // Now simulate shutdown, which should stop the timer.
|
| - factory()->ContextDestroyed();
|
| + EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
|
|
|
| - EXPECT_FALSE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_FALSE(factory()->IsBackingStorePendingClose(origin));
|
| + },
|
| + base::Unretained(context()),
|
| + base::MakeRefCounted<MockIndexedDBCallbacks>(
|
| + false /*expect_connection*/)));
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| TEST_F(IndexedDBFactoryTest, GetDatabaseNamesClosesBackingStore) {
|
| - const Origin origin(GURL("http://localhost:81"));
|
| -
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| -
|
| - EXPECT_FALSE(factory()->IsBackingStoreOpen(origin));
|
| -
|
| - const bool expect_connection = false;
|
| - scoped_refptr<MockIndexedDBCallbacks> callbacks(
|
| - new MockIndexedDBCallbacks(expect_connection));
|
| - factory()->GetDatabaseNames(callbacks, origin, temp_directory.GetPath(),
|
| - nullptr /* request_context */);
|
| -
|
| - EXPECT_TRUE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_TRUE(factory()->IsBackingStorePendingClose(origin));
|
| -
|
| - // Now simulate shutdown, which should stop the timer.
|
| - factory()->ContextDestroyed();
|
| -
|
| - EXPECT_FALSE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_FALSE(factory()->IsBackingStorePendingClose(origin));
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context,
|
| + scoped_refptr<MockIndexedDBCallbacks> callbacks) {
|
| + scoped_refptr<MockIDBFactory> factory =
|
| + base::MakeRefCounted<MockIDBFactory>(context);
|
| +
|
| + const Origin origin(GURL("http://localhost:81"));
|
| + EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
|
| +
|
| + factory->GetDatabaseNames(callbacks, origin, context->data_path(),
|
| + nullptr /* request_context */);
|
| +
|
| + EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
|
| +
|
| + // Now simulate shutdown, which should stop the timer.
|
| + factory->ContextDestroyed();
|
| +
|
| + EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
|
| +
|
| + },
|
| + base::Unretained(context()),
|
| + base::MakeRefCounted<MockIndexedDBCallbacks>(
|
| + false /*expect_connection*/)));
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| TEST_F(IndexedDBFactoryTest, ForceCloseReleasesBackingStore) {
|
| - const Origin origin(GURL("http://localhost:81"));
|
| -
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| -
|
| - scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks());
|
| - scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
|
| - new MockIndexedDBDatabaseCallbacks());
|
| - const int64_t transaction_id = 1;
|
| - std::unique_ptr<IndexedDBPendingConnection> connection(
|
| - base::MakeUnique<IndexedDBPendingConnection>(
|
| - callbacks, db_callbacks, 0 /* child_process_id */, transaction_id,
|
| - IndexedDBDatabaseMetadata::DEFAULT_VERSION));
|
| - factory()->Open(ASCIIToUTF16("db"), std::move(connection),
|
| - nullptr /* request_context */, origin,
|
| - temp_directory.GetPath());
|
| -
|
| - EXPECT_TRUE(callbacks->connection());
|
| - EXPECT_TRUE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_FALSE(factory()->IsBackingStorePendingClose(origin));
|
| -
|
| - callbacks->connection()->Close();
|
| -
|
| - EXPECT_TRUE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_TRUE(factory()->IsBackingStorePendingClose(origin));
|
| -
|
| - factory()->ForceClose(origin);
|
| -
|
| - EXPECT_FALSE(factory()->IsBackingStoreOpen(origin));
|
| - EXPECT_FALSE(factory()->IsBackingStorePendingClose(origin));
|
| -
|
| - // Ensure it is safe if the store is not open.
|
| - factory()->ForceClose(origin);
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context,
|
| + scoped_refptr<MockIndexedDBCallbacks> callbacks,
|
| + scoped_refptr<IndexedDBDatabaseCallbacks> db_callbacks) {
|
| + scoped_refptr<MockIDBFactory> factory =
|
| + base::MakeRefCounted<MockIDBFactory>(context);
|
| +
|
| + const Origin origin(GURL("http://localhost:81"));
|
| + const int64_t transaction_id = 1;
|
| + std::unique_ptr<IndexedDBPendingConnection> connection(
|
| + base::MakeUnique<IndexedDBPendingConnection>(
|
| + callbacks, db_callbacks, 0 /* child_process_id */,
|
| + transaction_id,
|
| + IndexedDBDatabaseMetadata::DEFAULT_VERSION));
|
| + factory->Open(ASCIIToUTF16("db"), std::move(connection),
|
| + nullptr /* request_context */, origin,
|
| + context->data_path());
|
| +
|
| + EXPECT_TRUE(callbacks->connection());
|
| + EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
|
| +
|
| + callbacks->connection()->Close();
|
| +
|
| + EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
|
| +
|
| + factory->ForceClose(origin);
|
| +
|
| + EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
|
| + EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
|
| +
|
| + // Ensure it is safe if the store is not open.
|
| + factory->ForceClose(origin);
|
| +
|
| + },
|
| + base::Unretained(context()),
|
| + base::MakeRefCounted<MockIndexedDBCallbacks>(),
|
| + base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>()));
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| class UpgradeNeededCallbacks : public MockIndexedDBCallbacks {
|
| @@ -469,56 +563,93 @@ class ErrorCallbacks : public MockIndexedDBCallbacks {
|
|
|
| TEST_F(IndexedDBFactoryTest, DatabaseFailedOpen) {
|
| const Origin origin(GURL("http://localhost:81"));
|
| -
|
| - base::ScopedTempDir temp_directory;
|
| - ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| -
|
| const base::string16 db_name(ASCIIToUTF16("db"));
|
| - const int64_t db_version = 2;
|
| const int64_t transaction_id = 1;
|
| - scoped_refptr<IndexedDBDatabaseCallbacks> db_callbacks(
|
| - new MockIndexedDBDatabaseCallbacks());
|
| -
|
| - // Open at version 2, then close.
|
| - {
|
| - scoped_refptr<UpgradeNeededCallbacks> callbacks(
|
| - new UpgradeNeededCallbacks());
|
| - std::unique_ptr<IndexedDBPendingConnection> connection(
|
| - base::MakeUnique<IndexedDBPendingConnection>(
|
| - callbacks, db_callbacks, 0 /* child_process_id */, transaction_id,
|
| - db_version));
|
| - factory()->Open(db_name, std::move(connection),
|
| - nullptr /* request_context */, origin,
|
| - temp_directory.GetPath());
|
| - EXPECT_TRUE(factory()->IsDatabaseOpen(origin, db_name));
|
| -
|
| - // Pump the message loop so the upgrade transaction can run.
|
| - base::RunLoop().RunUntilIdle();
|
| - EXPECT_TRUE(callbacks->connection());
|
| - callbacks->connection()->database()->Commit(
|
| - callbacks->connection()->GetTransaction(transaction_id));
|
| -
|
| - callbacks->connection()->Close();
|
| - EXPECT_FALSE(factory()->IsDatabaseOpen(origin, db_name));
|
| - }
|
| -
|
| - // Open at version < 2, which will fail; ensure factory doesn't retain
|
| - // the database object.
|
| - {
|
| - scoped_refptr<ErrorCallbacks> callbacks(new ErrorCallbacks());
|
| - std::unique_ptr<IndexedDBPendingConnection> connection(
|
| - base::MakeUnique<IndexedDBPendingConnection>(
|
| - callbacks, db_callbacks, 0 /* child_process_id */, transaction_id,
|
| - db_version - 1));
|
| - factory()->Open(db_name, std::move(connection),
|
| - nullptr /* request_context */, origin,
|
| - temp_directory.GetPath());
|
| - EXPECT_TRUE(callbacks->saw_error());
|
| - EXPECT_FALSE(factory()->IsDatabaseOpen(origin, db_name));
|
| - }
|
|
|
| - // Terminate all pending-close timers.
|
| - factory()->ForceClose(origin);
|
| + // These objects are retained across posted tasks, so despite being used
|
| + // exclusively on the IDB sequence.
|
| +
|
| + // Created and used on IDB sequence.
|
| + scoped_refptr<MockIDBFactory> factory;
|
| + // Created on IO thread, used on IDB sequence.
|
| + scoped_refptr<UpgradeNeededCallbacks> upgrade_callbacks =
|
| + base::MakeRefCounted<UpgradeNeededCallbacks>();
|
| +
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context,
|
| + scoped_refptr<MockIDBFactory>* factory,
|
| + scoped_refptr<UpgradeNeededCallbacks>* upgrade_callbacks,
|
| + scoped_refptr<IndexedDBDatabaseCallbacks> db_callbacks,
|
| + const base::string16& db_name, int64_t transaction_id,
|
| + const Origin& origin) {
|
| +
|
| + *factory = base::MakeRefCounted<MockIDBFactory>(context);
|
| +
|
| + // Open at version 2.
|
| + const int64_t db_version = 2;
|
| + (*factory)->Open(
|
| + db_name,
|
| + base::MakeUnique<IndexedDBPendingConnection>(
|
| + *upgrade_callbacks, db_callbacks, 0 /* child_process_id */,
|
| + transaction_id, db_version),
|
| + nullptr /* request_context */, origin, context->data_path());
|
| +
|
| + EXPECT_TRUE((*factory)->IsDatabaseOpen(origin, db_name));
|
| + },
|
| + base::Unretained(context()), base::Unretained(&factory),
|
| + base::Unretained(&upgrade_callbacks),
|
| + base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(), db_name,
|
| + transaction_id, origin));
|
| +
|
| + // Pump the message loop so the upgrade transaction can run.
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| +
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context,
|
| + scoped_refptr<MockIDBFactory> factory,
|
| + scoped_refptr<UpgradeNeededCallbacks> upgrade_callbacks,
|
| + scoped_refptr<ErrorCallbacks> failed_open_callbacks,
|
| + scoped_refptr<IndexedDBDatabaseCallbacks> db_callbacks,
|
| + const base::string16& db_name, int64_t transaction_id,
|
| + const Origin& origin) {
|
| + // Close the connection.
|
| + {
|
| + EXPECT_TRUE(upgrade_callbacks->connection());
|
| + upgrade_callbacks->connection()->database()->Commit(
|
| + upgrade_callbacks->connection()->GetTransaction(
|
| + transaction_id));
|
| + upgrade_callbacks->connection()->Close();
|
| + EXPECT_FALSE(factory->IsDatabaseOpen(origin, db_name));
|
| + }
|
| +
|
| + // Open at version < 2, which will fail; ensure factory doesn't
|
| + // retain the database object.
|
| + {
|
| + const int64_t db_version = 1;
|
| + std::unique_ptr<IndexedDBPendingConnection> connection(
|
| + base::MakeUnique<IndexedDBPendingConnection>(
|
| + failed_open_callbacks, db_callbacks,
|
| + 0 /* child_process_id */, transaction_id, db_version));
|
| + factory->Open(db_name, std::move(connection),
|
| + nullptr /* request_context */, origin,
|
| + context->data_path());
|
| + EXPECT_TRUE(failed_open_callbacks->saw_error());
|
| + EXPECT_FALSE(factory->IsDatabaseOpen(origin, db_name));
|
| + }
|
| +
|
| + // Terminate all pending-close timers.
|
| + factory->ForceClose(origin);
|
| + },
|
| + base::Unretained(context()), std::move(factory),
|
| + std::move(upgrade_callbacks), base::MakeRefCounted<ErrorCallbacks>(),
|
| + base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(), db_name,
|
| + transaction_id, origin));
|
| +
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| }
|
|
|
| namespace {
|
| @@ -552,22 +683,58 @@ TEST_F(IndexedDBFactoryTest, DataFormatVersion) {
|
| const IndexedDBDataFormatVersion& version) {
|
| base::AutoReset<IndexedDBDataFormatVersion> override_version(
|
| &IndexedDBDataFormatVersion::GetMutableCurrentForTesting(), version);
|
| - auto db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
|
| - auto callbacks = base::MakeRefCounted<DataLossCallbacks>();
|
| +
|
| + // These objects are retained across posted tasks, so despite being used
|
| + // exclusively on the IDB sequence.
|
| +
|
| + // Created and used on IDB sequence.
|
| + scoped_refptr<MockIDBFactory> factory;
|
| + // Created on IO thread, used on IDB sequence.
|
| + scoped_refptr<DataLossCallbacks> callbacks =
|
| + base::MakeRefCounted<DataLossCallbacks>();
|
| +
|
| const int64_t transaction_id = 1;
|
| - factory()->Open(ASCIIToUTF16("test_db"),
|
| - base::MakeUnique<IndexedDBPendingConnection>(
|
| - callbacks, db_callbacks, 0 /* child_process_id */,
|
| - transaction_id, 1 /* version */),
|
| - nullptr /* request_context */, origin,
|
| - context()->data_path());
|
| - base::RunLoop().RunUntilIdle();
|
| - auto* connection = callbacks->connection();
|
| - EXPECT_TRUE(connection);
|
| - connection->database()->Commit(connection->GetTransaction(transaction_id));
|
| - connection->Close();
|
| - factory()->ForceClose(origin);
|
| - return callbacks->data_loss();
|
| + blink::WebIDBDataLoss result;
|
| +
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](IndexedDBContextImpl* context,
|
| + scoped_refptr<MockIDBFactory>* factory,
|
| + scoped_refptr<DataLossCallbacks>* callbacks,
|
| + scoped_refptr<IndexedDBDatabaseCallbacks> db_callbacks,
|
| + const Origin& origin, int64_t transaction_id) {
|
| + *factory = base::MakeRefCounted<MockIDBFactory>(context);
|
| + (*factory)->Open(
|
| + ASCIIToUTF16("test_db"),
|
| + base::MakeUnique<IndexedDBPendingConnection>(
|
| + *callbacks, db_callbacks, 0 /* child_process_id */,
|
| + transaction_id, 1 /* version */),
|
| + nullptr /* request_context */, origin, context->data_path());
|
| + },
|
| + base::Unretained(context()), base::Unretained(&factory),
|
| + base::Unretained(&callbacks),
|
| + base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(), origin,
|
| + transaction_id));
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| + context()->TaskRunner()->PostTask(
|
| + FROM_HERE,
|
| + base::BindOnce(
|
| + [](scoped_refptr<MockIDBFactory> factory,
|
| + scoped_refptr<DataLossCallbacks> callbacks, const Origin& origin,
|
| + int64_t transaction_id, blink::WebIDBDataLoss* result) {
|
| + auto* connection = callbacks->connection();
|
| + EXPECT_TRUE(connection);
|
| + connection->database()->Commit(
|
| + connection->GetTransaction(transaction_id));
|
| + connection->Close();
|
| + factory->ForceClose(origin);
|
| + *result = callbacks->data_loss();
|
| + },
|
| + std::move(factory), std::move(callbacks), origin, transaction_id,
|
| + base::Unretained(&result)));
|
| + RunAllBlockingPoolTasksUntilIdle();
|
| + return result;
|
| };
|
|
|
| using blink::kWebIDBDataLossNone;
|
|
|