Commit 3569c091 authored by Adrienne Walker's avatar Adrienne Walker Committed by Commit Bot

indexeddb: convert some browser tests to IndexedDBControl

IndexedDBContext access is going away, and so these tests need to use
public mojo interfaces instead of private indexeddb interfaces.

This converts some easier browser tests over to using the new interface.

Bug: 1015214
Change-Id: I68bb1cd46ff6ae13d8b113d37886a499e0d97276
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2088337Reviewed-by: default avatarDaniel Murphy <dmurph@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Auto-Submit: enne <enne@chromium.org>
Commit-Queue: Kinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#747201}
parent d09dbab2
...@@ -9,12 +9,45 @@ import "mojo/public/mojom/base/values.mojom"; ...@@ -9,12 +9,45 @@ import "mojo/public/mojom/base/values.mojom";
import "mojo/public/mojom/base/time.mojom"; import "mojo/public/mojom/base/time.mojom";
import "url/mojom/origin.mojom"; import "url/mojom/origin.mojom";
enum V2SchemaCorruptionStatus {
CORRUPTION_UNKNOWN,
CORRUPTION_NO,
CORRUPTION_YES,
};
// A test-only interface extending storage.mojom.IndexedDBControl. // A test-only interface extending storage.mojom.IndexedDBControl.
interface IndexedDBControlTest { interface IndexedDBControlTest {
// Gets the root data path for storage.
GetBaseDataPathForTesting() => (mojo_base.mojom.FilePath path);
// Gets the file name of the local storage file for the given origin. // Gets the file name of the local storage file for the given origin.
GetFilePathForTesting(url.mojom.Origin origin) => GetFilePathForTesting(url.mojom.Origin origin) =>
(mojo_base.mojom.FilePath path); (mojo_base.mojom.FilePath path);
// Forgets the origins/sizes read from disk. // Forgets the origins/sizes read from disk.
ResetCachesForTesting() => (); ResetCachesForTesting() => ();
// Downgrades databases to V2.
ForceSchemaDowngradeForTesting(url.mojom.Origin origin) => (bool downgraded);
// Returns the corruption status for a given database.
HasV2SchemaCorruptionForTesting(url.mojom.Origin origin) =>
(V2SchemaCorruptionStatus status);
// Does a direct write to a database with a given key/value pair.
WriteToIndexedDBForTesting(url.mojom.Origin origin, string key,
string value) => ();
// Returns the number of blobs for a given origin.
GetBlobCountForTesting(url.mojom.Origin origin) => (int64 num_blobs);
// Returns the next blob id for a given origin.
GetNextBlobNumberForTesting(url.mojom.Origin origin, int64 database_id) =>
(int64 next_blob_number);
// Returns the path for a given origin/database/blob.
GetPathForBlobForTesting(url.mojom.Origin origin, int64 database_id,
int64 blob_number) =>
(mojo_base.mojom.FilePath path);
}; };
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "base/test/thread_test_helper.h" #include "base/test/thread_test_helper.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "components/services/storage/indexed_db/scopes/varint_coding.h"
#include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h" #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
#include "components/services/storage/public/mojom/indexed_db_control.mojom-test-utils.h" #include "components/services/storage/public/mojom/indexed_db_control.mojom-test-utils.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h"
...@@ -148,6 +147,7 @@ class IndexedDBBrowserTest : public ContentBrowserTest, ...@@ -148,6 +147,7 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
} }
// TODO(enne): remove this in favor of GetControl below.
IndexedDBContextImpl* GetContext(Shell* browser = nullptr) { IndexedDBContextImpl* GetContext(Shell* browser = nullptr) {
if (!browser) if (!browser)
browser = shell(); browser = shell();
...@@ -156,6 +156,24 @@ class IndexedDBBrowserTest : public ContentBrowserTest, ...@@ -156,6 +156,24 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
return partition->GetIndexedDBContextImplForTesting(); return partition->GetIndexedDBContextImplForTesting();
} }
storage::mojom::IndexedDBControl& GetControl(Shell* browser = nullptr) {
if (!browser)
browser = shell();
StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
browser->web_contents()->GetBrowserContext());
return partition->GetIndexedDBControl();
}
mojo::Remote<storage::mojom::IndexedDBControlTest> GetControlTest() {
auto* browser = shell();
StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
browser->web_contents()->GetBrowserContext());
auto& control = partition->GetIndexedDBControl();
mojo::Remote<storage::mojom::IndexedDBControlTest> idb_control_test;
control.BindTestInterface(idb_control_test.BindNewPipeAndPassReceiver());
return idb_control_test;
}
void SetQuota(int per_host_quota_kilobytes) { void SetQuota(int per_host_quota_kilobytes) {
SetTempQuota(per_host_quota_kilobytes, SetTempQuota(per_host_quota_kilobytes,
BrowserContext::GetDefaultStoragePartition( BrowserContext::GetDefaultStoragePartition(
...@@ -179,42 +197,41 @@ class IndexedDBBrowserTest : public ContentBrowserTest, ...@@ -179,42 +197,41 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
bool DeleteForOrigin(const url::Origin& origin, Shell* browser = nullptr) { bool DeleteForOrigin(const url::Origin& origin, Shell* browser = nullptr) {
base::RunLoop loop; base::RunLoop loop;
IndexedDBContextImpl* context = GetContext(browser); auto& control = GetControl(browser);
bool result = false; bool result = false;
context->IDBTaskRunner()->PostTask( control.DeleteForOrigin(origin,
FROM_HERE, base::BindLambdaForTesting([&]() { base::BindLambdaForTesting([&](bool success) {
context->DeleteForOrigin( result = success;
origin, base::BindLambdaForTesting([&](bool success) { loop.Quit();
result = success; }));
loop.Quit();
}));
}));
loop.Run(); loop.Run();
return result; return result;
} }
int64_t RequestUsage(const url::Origin& origin, Shell* browser = nullptr) { int64_t RequestUsage(const url::Origin& origin, Shell* browser = nullptr) {
base::RunLoop loop; base::RunLoop loop;
int64_t size; int64_t size = 0;
IndexedDBContextImpl* context = GetContext(browser); auto& control = GetControl(browser);
context->IDBTaskRunner()->PostTask( control.GetUsage(base::BindOnce(base::BindLambdaForTesting(
FROM_HERE, base::BindLambdaForTesting([&]() { [&](std::vector<storage::mojom::IndexedDBStorageUsageInfoPtr> usages) {
size = context->GetOriginDiskUsage(origin); for (auto& usage : usages)
size += usage->size_in_bytes;
loop.Quit(); loop.Quit();
})); })));
loop.Run(); loop.Run();
return size; return size;
} }
int RequestBlobFileCount(const url::Origin& origin) { int64_t RequestBlobFileCount(const url::Origin& origin) {
base::RunLoop loop; base::RunLoop loop;
int count; int64_t count = 0;
IndexedDBContextImpl* context = GetContext(); auto control_test = GetControlTest();
context->IDBTaskRunner()->PostTask( control_test->GetBlobCountForTesting(
FROM_HERE, base::BindLambdaForTesting([&]() { origin,
count = context->GetOriginBlobFileCount(origin); base::BindOnce(base::BindLambdaForTesting([&](int64_t returned_count) {
count = returned_count;
loop.Quit(); loop.Quit();
})); })));
loop.Run(); loop.Run();
return count; return count;
} }
...@@ -222,42 +239,40 @@ class IndexedDBBrowserTest : public ContentBrowserTest, ...@@ -222,42 +239,40 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
bool RequestSchemaDowngrade(const url::Origin& origin) { bool RequestSchemaDowngrade(const url::Origin& origin) {
base::RunLoop loop; base::RunLoop loop;
bool downgraded; bool downgraded;
IndexedDBContextImpl* context = GetContext(); auto control_test = GetControlTest();
context->IDBTaskRunner()->PostTask( control_test->ForceSchemaDowngradeForTesting(
FROM_HERE, base::BindLambdaForTesting([&]() { origin,
downgraded = context->ForceSchemaDowngrade(origin); base::BindOnce(base::BindLambdaForTesting([&](bool was_downgraded) {
downgraded = was_downgraded;
loop.Quit(); loop.Quit();
})); })));
loop.Run(); loop.Run();
return downgraded; return downgraded;
} }
V2SchemaCorruptionStatus RequestHasV2SchemaCorruption( storage::mojom::V2SchemaCorruptionStatus RequestHasV2SchemaCorruption(
const url::Origin& origin) { const url::Origin& origin) {
base::RunLoop loop; base::RunLoop loop;
V2SchemaCorruptionStatus status; storage::mojom::V2SchemaCorruptionStatus ret;
IndexedDBContextImpl* context = GetContext(); auto control_test = GetControlTest();
context->IDBTaskRunner()->PostTask( control_test->HasV2SchemaCorruptionForTesting(
FROM_HERE, base::BindLambdaForTesting([&]() { origin, base::BindLambdaForTesting(
status = context->HasV2SchemaCorruption(origin); [&](storage::mojom::V2SchemaCorruptionStatus status) {
loop.Quit(); ret = status;
})); loop.Quit();
}));
loop.Run(); loop.Run();
return status; return ret;
} }
// Synchronously writes to the IndexedDB database at the given origin by // Synchronously writes to the IndexedDB database at the given origin.
// posting a task to the idb task runner and waiting.
void WriteToIndexedDB(const url::Origin& origin, void WriteToIndexedDB(const url::Origin& origin,
std::string key, std::string key,
std::string value) { std::string value) {
auto control_test = GetControlTest();
base::RunLoop loop; base::RunLoop loop;
GetContext()->IDBTaskRunner()->PostTask( control_test->WriteToIndexedDBForTesting(
FROM_HERE, origin, std::move(key), std::move(value), loop.QuitClosure());
base::BindOnce(&IndexedDBBrowserTest::WriteToIndexedDBOnIDBSequence,
base::Unretained(this),
base::WrapRefCounted(GetContext()), origin,
std::move(key), std::move(value), loop.QuitClosure()));
loop.Run(); loop.Run();
} }
...@@ -273,33 +288,6 @@ class IndexedDBBrowserTest : public ContentBrowserTest, ...@@ -273,33 +288,6 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
} }
private: private:
void WriteToIndexedDBOnIDBSequence(
scoped_refptr<IndexedDBContextImpl> context,
const url::Origin& origin,
std::string key,
std::string value,
base::OnceClosure done) {
base::ScopedClosureRunner done_runner(std::move(done));
IndexedDBOriginStateHandle handle;
leveldb::Status s;
std::tie(handle, s, std::ignore, std::ignore, std::ignore) =
context->GetIDBFactory()->GetOrOpenOriginFactory(
origin, context->data_path(), /*create_if_missing=*/true);
CHECK(s.ok()) << s.ToString();
CHECK(handle.IsHeld());
TransactionalLevelDBDatabase* db =
handle.origin_state()->backing_store()->db();
s = db->Put(key, &value);
CHECK(s.ok()) << s.ToString();
handle.Release();
context->GetIDBFactory()->ForceClose(origin, true);
CHECK(!context->GetIDBFactory()->IsBackingStoreOpen(origin));
context.reset();
}
DISALLOW_COPY_AND_ASSIGN(IndexedDBBrowserTest); DISALLOW_COPY_AND_ASSIGN(IndexedDBBrowserTest);
}; };
...@@ -461,31 +449,29 @@ struct BlobModificationTime { ...@@ -461,31 +449,29 @@ struct BlobModificationTime {
static void CopyLevelDBToProfile( static void CopyLevelDBToProfile(
Shell* shell, Shell* shell,
scoped_refptr<IndexedDBContextImpl> context, const base::FilePath& data_path,
const std::string& test_directory, const std::string& test_directory,
std::vector<BlobModificationTime> modification_times) { std::vector<BlobModificationTime> modification_times) {
DCHECK(context->IDBTaskRunner()->RunsTasksInCurrentSequence());
base::FilePath leveldb_dir(FILE_PATH_LITERAL("file__0.indexeddb.leveldb")); base::FilePath leveldb_dir(FILE_PATH_LITERAL("file__0.indexeddb.leveldb"));
base::FilePath blob_dir(FILE_PATH_LITERAL("file__0.indexeddb.blob")); base::FilePath blob_dir(FILE_PATH_LITERAL("file__0.indexeddb.blob"));
base::FilePath test_leveldb_data_dir = base::FilePath test_leveldb_data_dir =
GetTestFilePath("indexeddb", test_directory.c_str()).Append(leveldb_dir); GetTestFilePath("indexeddb", test_directory.c_str()).Append(leveldb_dir);
base::FilePath test_blob_data_dir = base::FilePath test_blob_data_dir =
GetTestFilePath("indexeddb", test_directory.c_str()).Append(blob_dir); GetTestFilePath("indexeddb", test_directory.c_str()).Append(blob_dir);
base::FilePath leveldb_dest = context->data_path().Append(leveldb_dir); base::FilePath leveldb_dest = data_path.Append(leveldb_dir);
base::FilePath blob_dest = context->data_path().Append(blob_dir); base::FilePath blob_dest = data_path.Append(blob_dir);
// If we don't create the destination directories first, the contents of the // If we don't create the destination directories first, the contents of the
// leveldb directory are copied directly into profile/IndexedDB instead of // leveldb directory are copied directly into profile/IndexedDB instead of
// profile/IndexedDB/file__0.xxx/ // profile/IndexedDB/file__0.xxx/
ASSERT_TRUE(base::CreateDirectory(leveldb_dest)); ASSERT_TRUE(base::CreateDirectory(leveldb_dest));
const bool kRecursive = true; const bool kRecursive = true;
ASSERT_TRUE(base::CopyDirectory(test_leveldb_data_dir, context->data_path(), ASSERT_TRUE(
kRecursive)); base::CopyDirectory(test_leveldb_data_dir, data_path, kRecursive));
if (!base::PathExists(test_blob_data_dir)) if (!base::PathExists(test_blob_data_dir))
return; return;
ASSERT_TRUE(base::CreateDirectory(blob_dest)); ASSERT_TRUE(base::CreateDirectory(blob_dest));
ASSERT_TRUE(base::CopyDirectory(test_blob_data_dir, context->data_path(), ASSERT_TRUE(base::CopyDirectory(test_blob_data_dir, data_path, kRecursive));
kRecursive));
// For some reason touching files on Android fails with EPERM. // For some reason touching files on Android fails with EPERM.
// https://crbug.com/1045488 // https://crbug.com/1045488
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
...@@ -501,16 +487,17 @@ static void CopyLevelDBToProfile( ...@@ -501,16 +487,17 @@ static void CopyLevelDBToProfile(
class IndexedDBBrowserTestWithPreexistingLevelDB : public IndexedDBBrowserTest { class IndexedDBBrowserTestWithPreexistingLevelDB : public IndexedDBBrowserTest {
public: public:
IndexedDBBrowserTestWithPreexistingLevelDB() {} IndexedDBBrowserTestWithPreexistingLevelDB() = default;
void SetUpOnMainThread() override { void SetUpOnMainThread() override {
scoped_refptr<IndexedDBContextImpl> context = GetContext(); base::RunLoop loop;
context->IDBTaskRunner()->PostTask( auto control_test = GetControlTest();
FROM_HERE, control_test->GetBaseDataPathForTesting(
base::BindOnce(&CopyLevelDBToProfile, shell(), context, base::BindLambdaForTesting([&](const base::FilePath& data_path) {
EnclosingLevelDBDir(), CustomModificationTimes())); CopyLevelDBToProfile(shell(), data_path, EnclosingLevelDBDir(),
scoped_refptr<base::ThreadTestHelper> helper( CustomModificationTimes());
new base::ThreadTestHelper(GetContext()->IDBTaskRunner())); loop.Quit();
ASSERT_TRUE(helper->Run()); }));
loop.Run();
} }
virtual std::string EnclosingLevelDBDir() = 0; virtual std::string EnclosingLevelDBDir() = 0;
...@@ -668,8 +655,17 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, LevelDBLogFileTest) { ...@@ -668,8 +655,17 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, LevelDBLogFileTest) {
SimpleTest(GetTestUrl("indexeddb", "database_test.html")); SimpleTest(GetTestUrl("indexeddb", "database_test.html"));
base::FilePath leveldb_dir(FILE_PATH_LITERAL("file__0.indexeddb.leveldb")); base::FilePath leveldb_dir(FILE_PATH_LITERAL("file__0.indexeddb.leveldb"));
base::FilePath log_file(FILE_PATH_LITERAL("LOG")); base::FilePath log_file(FILE_PATH_LITERAL("LOG"));
base::FilePath log_file_path =
GetContext()->data_path().Append(leveldb_dir).Append(log_file); base::FilePath log_file_path;
base::RunLoop loop;
auto control_test = GetControlTest();
control_test->GetBaseDataPathForTesting(
base::BindLambdaForTesting([&](const base::FilePath& path) {
log_file_path = path.Append(leveldb_dir).Append(log_file);
loop.Quit();
}));
loop.Run();
{ {
base::ScopedAllowBlockingForTesting allow_blocking; base::ScopedAllowBlockingForTesting allow_blocking;
int64_t size; int64_t size;
...@@ -707,14 +703,6 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, EmptyBlob) { ...@@ -707,14 +703,6 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, EmptyBlob) {
// Very flaky on many bots. See crbug.com/459835 // Very flaky on many bots. See crbug.com/459835
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, DISABLED_BlobDidAck) { IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, DISABLED_BlobDidAck) {
SimpleTest(GetTestUrl("indexeddb", "blob_did_ack.html")); SimpleTest(GetTestUrl("indexeddb", "blob_did_ack.html"));
// Wait for idle so that the blob ack has time to be received/processed by
// the browser process.
scoped_refptr<base::ThreadTestHelper> helper =
base::MakeRefCounted<base::ThreadTestHelper>(
GetContext()->IDBTaskRunner());
ASSERT_TRUE(helper->Run());
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(helper->Run());
content::ChromeBlobStorageContext* blob_context = content::ChromeBlobStorageContext* blob_context =
ChromeBlobStorageContext::GetFor( ChromeBlobStorageContext::GetFor(
shell()->web_contents()->GetBrowserContext()); shell()->web_contents()->GetBrowserContext());
...@@ -724,10 +712,11 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, DISABLED_BlobDidAck) { ...@@ -724,10 +712,11 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, DISABLED_BlobDidAck) {
// Flaky. See crbug.com/459835. // Flaky. See crbug.com/459835.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed,
DISABLED_BlobDidAckPrefetch) { DISABLED_BlobDidAckPrefetch) {
SimpleTest(GetTestUrl("indexeddb", "blob_did_ack_prefetch.html")); const GURL kTestUrl = GetTestUrl("indexeddb", "blob_did_ack_prefetch.html");
// Wait for idle so that the blob ack has time to be received/processed by SimpleTest(kTestUrl);
// the browser process. const url::Origin kTestOrigin = url::Origin::Create(kTestUrl);
base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, RequestBlobFileCount(kTestOrigin));
content::ChromeBlobStorageContext* blob_context = content::ChromeBlobStorageContext* blob_context =
ChromeBlobStorageContext::GetFor( ChromeBlobStorageContext::GetFor(
shell()->web_contents()->GetBrowserContext()); shell()->web_contents()->GetBrowserContext());
...@@ -1005,23 +994,11 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteCompactsBackingStore) { ...@@ -1005,23 +994,11 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteCompactsBackingStore) {
const GURL kTestUrl = GetTestUrl("indexeddb", "delete_compact.html"); const GURL kTestUrl = GetTestUrl("indexeddb", "delete_compact.html");
const url::Origin kTestOrigin = url::Origin::Create(kTestUrl); const url::Origin kTestOrigin = url::Origin::Create(kTestUrl);
SimpleTest(GURL(kTestUrl.spec() + "#fill")); SimpleTest(GURL(kTestUrl.spec() + "#fill"));
{
// Cycle through the task runner to ensure that all IDB tasks are completed.
base::RunLoop loop;
GetContext()->IDBTaskRunner()->PostTask(FROM_HERE, loop.QuitClosure());
loop.Run();
}
int64_t after_filling = RequestUsage(kTestOrigin); int64_t after_filling = RequestUsage(kTestOrigin);
EXPECT_GT(after_filling, 0); EXPECT_GT(after_filling, 0);
SimpleTest(GURL(kTestUrl.spec() + "#purge")); SimpleTest(GURL(kTestUrl.spec() + "#purge"));
{
// Cycle through the task runner to ensure that the cleanup task is
// executed.
base::RunLoop loop;
GetContext()->IDBTaskRunner()->PostTask(FROM_HERE, loop.QuitClosure());
loop.Run();
}
int64_t after_deleting = RequestUsage(kTestOrigin); int64_t after_deleting = RequestUsage(kTestOrigin);
EXPECT_LT(after_deleting, after_filling); EXPECT_LT(after_deleting, after_filling);
...@@ -1162,9 +1139,10 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestV2SchemaCorruption, LifecycleTest) { ...@@ -1162,9 +1139,10 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestV2SchemaCorruption, LifecycleTest) {
SimpleTest(embedded_test_server()->GetURL(test_file)); SimpleTest(embedded_test_server()->GetURL(test_file));
// Verify the backing store does not have corruption. // Verify the backing store does not have corruption.
V2SchemaCorruptionStatus has_corruption = storage::mojom::V2SchemaCorruptionStatus has_corruption =
RequestHasV2SchemaCorruption(origin); RequestHasV2SchemaCorruption(origin);
ASSERT_EQ(has_corruption, V2SchemaCorruptionStatus::kNo); ASSERT_EQ(has_corruption,
storage::mojom::V2SchemaCorruptionStatus::CORRUPTION_NO);
// Revert schema to v2. This closes the targeted backing store. // Revert schema to v2. This closes the targeted backing store.
bool schema_downgrade = RequestSchemaDowngrade(origin); bool schema_downgrade = RequestSchemaDowngrade(origin);
...@@ -1175,7 +1153,8 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestV2SchemaCorruption, LifecycleTest) { ...@@ -1175,7 +1153,8 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestV2SchemaCorruption, LifecycleTest) {
std::string(s_indexeddb_test_prefix) + "v2schemacorrupt_reopen.html"; std::string(s_indexeddb_test_prefix) + "v2schemacorrupt_reopen.html";
SimpleTest(embedded_test_server()->GetURL(test_file)); SimpleTest(embedded_test_server()->GetURL(test_file));
has_corruption = RequestHasV2SchemaCorruption(origin); has_corruption = RequestHasV2SchemaCorruption(origin);
ASSERT_EQ(has_corruption, V2SchemaCorruptionStatus::kYes); ASSERT_EQ(has_corruption,
storage::mojom::V2SchemaCorruptionStatus::CORRUPTION_YES);
// Verify that the saved blob is get-able with a v2 backing store. // Verify that the saved blob is get-able with a v2 backing store.
test_file = test_file =
...@@ -1214,32 +1193,13 @@ class IndexedDBBrowserTestBlobKeyCorruption : public IndexedDBBrowserTest { ...@@ -1214,32 +1193,13 @@ class IndexedDBBrowserTestBlobKeyCorruption : public IndexedDBBrowserTest {
int64_t GetNextBlobNumber(const url::Origin& origin, int64_t database_id) { int64_t GetNextBlobNumber(const url::Origin& origin, int64_t database_id) {
int64_t number; int64_t number;
base::RunLoop loop; base::RunLoop loop;
IndexedDBContextImpl* context = GetContext(); auto control_test = GetControlTest();
context->IDBTaskRunner()->PostTask( control_test->GetNextBlobNumberForTesting(
FROM_HERE, base::BindLambdaForTesting([&]() { origin, database_id,
IndexedDBOriginStateHandle handle; base::BindLambdaForTesting([&](int64_t next_blob_number) {
leveldb::Status s; number = next_blob_number;
std::tie(handle, s, std::ignore, std::ignore, std::ignore) =
context->GetIDBFactory()->GetOrOpenOriginFactory(
origin, context->data_path(), /*create_if_missing=*/true);
CHECK(s.ok()) << s.ToString();
CHECK(handle.IsHeld());
TransactionalLevelDBDatabase* db =
handle.origin_state()->backing_store()->db();
const std::string key_gen_key = DatabaseMetaDataKey::Encode(
database_id,
DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
std::string data;
bool found = false;
bool ok = db->Get(key_gen_key, &data, &found).ok();
CHECK(found);
CHECK(ok);
base::StringPiece slice(data);
CHECK(DecodeVarInt(&slice, &number));
CHECK(DatabaseMetaDataKey::IsValidBlobNumber(number));
loop.Quit(); loop.Quit();
})); }));
loop.Run(); loop.Run();
...@@ -1251,20 +1211,11 @@ class IndexedDBBrowserTestBlobKeyCorruption : public IndexedDBBrowserTest { ...@@ -1251,20 +1211,11 @@ class IndexedDBBrowserTestBlobKeyCorruption : public IndexedDBBrowserTest {
int64_t blob_number) { int64_t blob_number) {
base::FilePath path; base::FilePath path;
base::RunLoop loop; base::RunLoop loop;
IndexedDBContextImpl* context = GetContext(); auto control_test = GetControlTest();
context->IDBTaskRunner()->PostTask( control_test->GetPathForBlobForTesting(
FROM_HERE, base::BindLambdaForTesting([&]() { origin, database_id, blob_number,
IndexedDBOriginStateHandle handle; base::BindLambdaForTesting([&](const base::FilePath& blob_path) {
leveldb::Status s; path = blob_path;
std::tie(handle, s, std::ignore, std::ignore, std::ignore) =
context->GetIDBFactory()->GetOrOpenOriginFactory(
origin, context->data_path(), /*create_if_missing=*/true);
CHECK(s.ok()) << s.ToString();
CHECK(handle.IsHeld());
IndexedDBBackingStore* backing_store =
handle.origin_state()->backing_store();
path = backing_store->GetBlobFileName(database_id, blob_number);
loop.Quit(); loop.Quit();
})); }));
loop.Run(); loop.Run();
......
...@@ -25,12 +25,17 @@ ...@@ -25,12 +25,17 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "base/values.h" #include "base/values.h"
#include "components/services/storage/indexed_db/leveldb/leveldb_factory.h" #include "components/services/storage/indexed_db/leveldb/leveldb_factory.h"
#include "components/services/storage/indexed_db/scopes/varint_coding.h"
#include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/indexed_db/indexed_db_class_factory.h" #include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/indexed_db_connection.h" #include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_database.h" #include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h" #include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
#include "content/browser/indexed_db/indexed_db_factory_impl.h" #include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/indexed_db_leveldb_operations.h" #include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
#include "content/browser/indexed_db/indexed_db_origin_state.h"
#include "content/browser/indexed_db/indexed_db_origin_state_handle.h"
#include "content/browser/indexed_db/indexed_db_quota_client.h" #include "content/browser/indexed_db/indexed_db_quota_client.h"
#include "content/browser/indexed_db/indexed_db_tracing.h" #include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction.h" #include "content/browser/indexed_db/indexed_db_transaction.h"
...@@ -407,18 +412,6 @@ void IndexedDBContextImpl::BindTestInterface( ...@@ -407,18 +412,6 @@ void IndexedDBContextImpl::BindTestInterface(
test_receivers_.Add(this, std::move(receiver)); test_receivers_.Add(this, std::move(receiver));
} }
void IndexedDBContextImpl::GetFilePathForTesting(
const Origin& origin,
GetFilePathForTestingCallback callback) {
std::move(callback).Run(GetLevelDBPath(origin));
}
void IndexedDBContextImpl::ResetCachesForTesting(base::OnceClosure callback) {
origin_set_.reset();
origin_size_map_.clear();
std::move(callback).Run();
}
void IndexedDBContextImpl::AddObserver( void IndexedDBContextImpl::AddObserver(
mojo::PendingRemote<storage::mojom::IndexedDBObserver> observer) { mojo::PendingRemote<storage::mojom::IndexedDBObserver> observer) {
IDBTaskRunner()->PostTask( IDBTaskRunner()->PostTask(
...@@ -432,26 +425,147 @@ void IndexedDBContextImpl::AddObserver( ...@@ -432,26 +425,147 @@ void IndexedDBContextImpl::AddObserver(
base::Unretained(this), std::move(observer))); base::Unretained(this), std::move(observer)));
} }
void IndexedDBContextImpl::ForceCloseSync( void IndexedDBContextImpl::GetBaseDataPathForTesting(
GetBaseDataPathForTestingCallback callback) {
std::move(callback).Run(data_path());
}
void IndexedDBContextImpl::GetFilePathForTesting(
const Origin& origin, const Origin& origin,
storage::mojom::ForceCloseReason reason) { GetFilePathForTestingCallback callback) {
ForceClose(origin, reason, base::DoNothing()); std::move(callback).Run(GetLevelDBPath(origin));
}
void IndexedDBContextImpl::ResetCachesForTesting(base::OnceClosure callback) {
origin_set_.reset();
origin_size_map_.clear();
std::move(callback).Run();
} }
bool IndexedDBContextImpl::ForceSchemaDowngrade(const Origin& origin) { void IndexedDBContextImpl::ForceSchemaDowngradeForTesting(
const url::Origin& origin,
ForceSchemaDowngradeForTestingCallback callback) {
DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
if (is_incognito() || !HasOrigin(origin)) if (is_incognito() || !HasOrigin(origin)) {
return false; std::move(callback).Run(false);
return;
}
if (indexeddb_factory_.get()) { if (indexeddb_factory_.get()) {
indexeddb_factory_->ForceSchemaDowngrade(origin); indexeddb_factory_->ForceSchemaDowngrade(origin);
return true; std::move(callback).Run(true);
return;
} }
ForceCloseSync( ForceCloseSync(
origin, origin,
storage::mojom::ForceCloseReason::FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE); storage::mojom::ForceCloseReason::FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE);
return false; std::move(callback).Run(false);
}
void IndexedDBContextImpl::HasV2SchemaCorruptionForTesting(
const url::Origin& origin,
HasV2SchemaCorruptionForTestingCallback callback) {
DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
if (is_incognito() || !HasOrigin(origin)) {
std::move(callback).Run(
storage::mojom::V2SchemaCorruptionStatus::CORRUPTION_UNKNOWN);
}
if (indexeddb_factory_.get()) {
std::move(callback).Run(
static_cast<storage::mojom::V2SchemaCorruptionStatus>(
indexeddb_factory_->HasV2SchemaCorruption(origin)));
return;
}
return std::move(callback).Run(
storage::mojom::V2SchemaCorruptionStatus::CORRUPTION_UNKNOWN);
}
void IndexedDBContextImpl::WriteToIndexedDBForTesting(
const url::Origin& origin,
const std::string& key,
const std::string& value,
base::OnceClosure callback) {
IndexedDBOriginStateHandle handle;
leveldb::Status s;
std::tie(handle, s, std::ignore, std::ignore, std::ignore) =
GetIDBFactory()->GetOrOpenOriginFactory(origin, data_path(),
/*create_if_missing=*/true);
CHECK(s.ok()) << s.ToString();
CHECK(handle.IsHeld());
TransactionalLevelDBDatabase* db =
handle.origin_state()->backing_store()->db();
std::string value_copy = value;
s = db->Put(key, &value_copy);
CHECK(s.ok()) << s.ToString();
handle.Release();
GetIDBFactory()->ForceClose(origin, true);
std::move(callback).Run();
}
void IndexedDBContextImpl::GetBlobCountForTesting(
const Origin& origin,
GetBlobCountForTestingCallback callback) {
std::move(callback).Run(GetOriginBlobFileCount(origin));
}
void IndexedDBContextImpl::GetNextBlobNumberForTesting(
const Origin& origin,
int64_t database_id,
GetNextBlobNumberForTestingCallback callback) {
IndexedDBOriginStateHandle handle;
leveldb::Status s;
std::tie(handle, s, std::ignore, std::ignore, std::ignore) =
GetIDBFactory()->GetOrOpenOriginFactory(origin, data_path(),
/*create_if_missing=*/true);
CHECK(s.ok()) << s.ToString();
CHECK(handle.IsHeld());
TransactionalLevelDBDatabase* db =
handle.origin_state()->backing_store()->db();
const std::string key_gen_key = DatabaseMetaDataKey::Encode(
database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
std::string data;
bool found = false;
bool ok = db->Get(key_gen_key, &data, &found).ok();
CHECK(found);
CHECK(ok);
base::StringPiece slice(data);
int64_t number;
CHECK(DecodeVarInt(&slice, &number));
CHECK(DatabaseMetaDataKey::IsValidBlobNumber(number));
std::move(callback).Run(number);
}
void IndexedDBContextImpl::GetPathForBlobForTesting(
const url::Origin& origin,
int64_t database_id,
int64_t blob_number,
GetPathForBlobForTestingCallback callback) {
IndexedDBOriginStateHandle handle;
leveldb::Status s;
std::tie(handle, s, std::ignore, std::ignore, std::ignore) =
GetIDBFactory()->GetOrOpenOriginFactory(origin, data_path(),
/*create_if_missing=*/true);
CHECK(s.ok()) << s.ToString();
CHECK(handle.IsHeld());
IndexedDBBackingStore* backing_store = handle.origin_state()->backing_store();
base::FilePath path =
backing_store->GetBlobFileName(database_id, blob_number);
std::move(callback).Run(path);
}
void IndexedDBContextImpl::ForceCloseSync(
const Origin& origin,
storage::mojom::ForceCloseReason reason) {
ForceClose(origin, reason, base::DoNothing());
} }
IndexedDBFactoryImpl* IndexedDBContextImpl::GetIDBFactory() { IndexedDBFactoryImpl* IndexedDBContextImpl::GetIDBFactory() {
...@@ -522,18 +636,6 @@ base::Time IndexedDBContextImpl::GetOriginLastModified(const Origin& origin) { ...@@ -522,18 +636,6 @@ base::Time IndexedDBContextImpl::GetOriginLastModified(const Origin& origin) {
return file_info.last_modified; return file_info.last_modified;
} }
V2SchemaCorruptionStatus IndexedDBContextImpl::HasV2SchemaCorruption(
const Origin& origin) {
DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
if (is_incognito() || !HasOrigin(origin))
return V2SchemaCorruptionStatus::kUnknown;
if (indexeddb_factory_.get())
return indexeddb_factory_->HasV2SchemaCorruption(origin);
return V2SchemaCorruptionStatus::kUnknown;
}
size_t IndexedDBContextImpl::GetConnectionCountSync(const Origin& origin) { size_t IndexedDBContextImpl::GetConnectionCountSync(const Origin& origin) {
DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
if (!HasOrigin(origin)) if (!HasOrigin(origin))
......
...@@ -88,13 +88,36 @@ class CONTENT_EXPORT IndexedDBContextImpl ...@@ -88,13 +88,36 @@ class CONTENT_EXPORT IndexedDBContextImpl
void BindTestInterface( void BindTestInterface(
mojo::PendingReceiver<storage::mojom::IndexedDBControlTest> receiver) mojo::PendingReceiver<storage::mojom::IndexedDBControlTest> receiver)
override; override;
void AddObserver(
mojo::PendingRemote<storage::mojom::IndexedDBObserver> observer) override;
// mojom::IndexedDBControlTest implementation: // mojom::IndexedDBControlTest implementation:
void GetBaseDataPathForTesting(
GetBaseDataPathForTestingCallback callback) override;
void GetFilePathForTesting(const url::Origin& origin, void GetFilePathForTesting(const url::Origin& origin,
GetFilePathForTestingCallback callback) override; GetFilePathForTestingCallback callback) override;
void ResetCachesForTesting(base::OnceClosure callback) override; void ResetCachesForTesting(base::OnceClosure callback) override;
void AddObserver( void ForceSchemaDowngradeForTesting(
mojo::PendingRemote<storage::mojom::IndexedDBObserver> observer) override; const url::Origin& origin,
ForceSchemaDowngradeForTestingCallback callback) override;
void HasV2SchemaCorruptionForTesting(
const url::Origin& origin,
HasV2SchemaCorruptionForTestingCallback callback) override;
void WriteToIndexedDBForTesting(const url::Origin& origin,
const std::string& key,
const std::string& value,
base::OnceClosure callback) override;
void GetBlobCountForTesting(const url::Origin& origin,
GetBlobCountForTestingCallback callback) override;
void GetNextBlobNumberForTesting(
const url::Origin& origin,
int64_t database_id,
GetNextBlobNumberForTestingCallback callback) override;
void GetPathForBlobForTesting(
const url::Origin& origin,
int64_t database_id,
int64_t blob_number,
GetPathForBlobForTestingCallback callback) override;
// TODO(enne): fix internal indexeddb callers to use ForceClose async instead. // TODO(enne): fix internal indexeddb callers to use ForceClose async instead.
void ForceCloseSync(const url::Origin& origin, void ForceCloseSync(const url::Origin& origin,
...@@ -135,8 +158,6 @@ class CONTENT_EXPORT IndexedDBContextImpl ...@@ -135,8 +158,6 @@ class CONTENT_EXPORT IndexedDBContextImpl
// Used by IndexedDBInternalsUI to populate internals page. // Used by IndexedDBInternalsUI to populate internals page.
base::ListValue* GetAllOriginsDetails(); base::ListValue* GetAllOriginsDetails();
bool ForceSchemaDowngrade(const url::Origin& origin);
V2SchemaCorruptionStatus HasV2SchemaCorruption(const url::Origin& origin);
// GetStoragePaths returns all paths owned by this database, in arbitrary // GetStoragePaths returns all paths owned by this database, in arbitrary
// order. // order.
std::vector<base::FilePath> GetStoragePaths(const url::Origin& origin) const; std::vector<base::FilePath> GetStoragePaths(const url::Origin& origin) const;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment