1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
content / browser / indexed_db / file_path_util.cc [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/indexed_db/file_path_util.h"
#include <inttypes.h>
#include "base/files/file_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/stringprintf.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "storage/common/database/database_identifier.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
namespace content::indexed_db {
namespace {
constexpr base::FilePath::CharType kBlobExtension[] =
FILE_PATH_LITERAL(".blob");
} // namespace
const base::FilePath::CharType kLevelDBExtension[] =
FILE_PATH_LITERAL(".leveldb");
const base::FilePath::CharType kIndexedDBExtension[] =
FILE_PATH_LITERAL(".indexeddb");
const base::FilePath::CharType kIndexedDBFile[] =
FILE_PATH_LITERAL("indexeddb");
bool ShouldUseLegacyFilePath(const storage::BucketLocator& bucket_locator) {
return bucket_locator.storage_key.IsFirstPartyContext() &&
bucket_locator.is_default;
}
base::FilePath GetBlobStoreFileName(
const storage::BucketLocator& bucket_locator) {
if (ShouldUseLegacyFilePath(bucket_locator)) {
// First-party blob files, for legacy reasons, are stored at:
// {{first_party_data_path}}/{{serialized_origin}}.indexeddb.blob
return base::FilePath()
.AppendASCII(storage::GetIdentifierFromOrigin(
bucket_locator.storage_key.origin()))
.AddExtension(kIndexedDBExtension)
.AddExtension(kBlobExtension);
}
// Third-party blob files are stored at:
// {{third_party_data_path}}/{{bucket_id}}/IndexedDB/indexeddb.blob
return base::FilePath(kIndexedDBFile).AddExtension(kBlobExtension);
}
base::FilePath GetLevelDBFileName(
const storage::BucketLocator& bucket_locator) {
if (ShouldUseLegacyFilePath(bucket_locator)) {
// First-party leveldb files, for legacy reasons, are stored at:
// {{first_party_data_path}}/{{serialized_origin}}.indexeddb.leveldb
// TODO(crbug.com/40855748): Migrate all first party buckets to the new
// path.
return base::FilePath()
.AppendASCII(storage::GetIdentifierFromOrigin(
bucket_locator.storage_key.origin()))
.AddExtension(kIndexedDBExtension)
.AddExtension(kLevelDBExtension);
}
// Third-party leveldb files are stored at:
// {{third_party_data_path}}/{{bucket_id}}/IndexedDB/indexeddb.leveldb
return base::FilePath(kIndexedDBFile).AddExtension(kLevelDBExtension);
}
base::FilePath GetBlobDirectoryName(const base::FilePath& path_base,
int64_t database_id) {
return path_base.AppendASCII(base::StringPrintf("%" PRIx64, database_id));
}
base::FilePath GetBlobDirectoryNameForKey(const base::FilePath& path_base,
int64_t database_id,
int64_t blob_number) {
base::FilePath path = GetBlobDirectoryName(path_base, database_id);
path = path.AppendASCII(base::StringPrintf(
"%02x", static_cast<int>(blob_number & 0x000000000000ff00) >> 8));
return path;
}
base::FilePath GetBlobFileNameForKey(const base::FilePath& path_base,
int64_t database_id,
int64_t blob_number) {
base::FilePath path =
GetBlobDirectoryNameForKey(path_base, database_id, blob_number);
path = path.AppendASCII(base::StringPrintf("%" PRIx64, blob_number));
return path;
}
bool IsPathTooLong(const base::FilePath& leveldb_dir) {
int limit = base::GetMaximumPathComponentLength(leveldb_dir.DirName());
if (limit < 0) {
DLOG(WARNING) << "GetMaximumPathComponentLength returned -1";
// In limited testing, ChromeOS returns 143, other OSes 255.
#if BUILDFLAG(IS_CHROMEOS)
limit = 143;
#else
limit = 255;
#endif
}
size_t component_length = leveldb_dir.BaseName().value().length();
if (component_length > static_cast<uint32_t>(limit)) {
DLOG(WARNING) << "Path component length (" << component_length
<< ") exceeds maximum (" << limit
<< ") allowed by this filesystem.";
const int min = 140;
const int max = 300;
const int num_buckets = 12;
base::UmaHistogramCustomCounts(
"WebCore.IndexedDB.BackingStore.OverlyLargeOriginLength",
component_length, min, max, num_buckets);
return true;
}
return false;
}
} // namespace content::indexed_db