1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "storage/browser/fileapi/sandbox_prioritized_origin_database.h"
7 #include "base/files/file.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/logging.h"
11 #include "base/pickle.h"
12 #include "storage/browser/fileapi/sandbox_isolated_origin_database.h"
13 #include "storage/browser/fileapi/sandbox_origin_database.h"
19 const base::FilePath::CharType kPrimaryDirectory
[] =
20 FILE_PATH_LITERAL("primary");
21 const base::FilePath::CharType kPrimaryOriginFile
[] =
22 FILE_PATH_LITERAL("primary.origin");
24 bool WritePrimaryOriginFile(const base::FilePath
& path
,
25 const std::string
& origin
) {
26 base::File
file(path
, base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_WRITE
);
32 pickle
.WriteString(origin
);
33 file
.Write(0, static_cast<const char*>(pickle
.data()), pickle
.size());
38 bool ReadPrimaryOriginFile(const base::FilePath
& path
,
39 std::string
* origin
) {
41 if (!base::ReadFileToString(path
, &buffer
))
43 Pickle
pickle(buffer
.data(), buffer
.size());
44 PickleIterator
iter(pickle
);
45 return pickle
.ReadString(&iter
, origin
) && !origin
->empty();
50 SandboxPrioritizedOriginDatabase::SandboxPrioritizedOriginDatabase(
51 const base::FilePath
& file_system_directory
,
52 leveldb::Env
* env_override
)
53 : file_system_directory_(file_system_directory
),
54 env_override_(env_override
),
56 file_system_directory_
.Append(kPrimaryOriginFile
)) {
59 SandboxPrioritizedOriginDatabase::~SandboxPrioritizedOriginDatabase() {
62 bool SandboxPrioritizedOriginDatabase::InitializePrimaryOrigin(
63 const std::string
& origin
) {
64 if (!primary_origin_database_
) {
65 if (!MaybeLoadPrimaryOrigin() && ResetPrimaryOrigin(origin
)) {
66 MaybeMigrateDatabase(origin
);
67 primary_origin_database_
.reset(
68 new SandboxIsolatedOriginDatabase(
70 file_system_directory_
,
71 base::FilePath(kPrimaryDirectory
)));
76 if (primary_origin_database_
)
77 return primary_origin_database_
->HasOriginPath(origin
);
82 std::string
SandboxPrioritizedOriginDatabase::GetPrimaryOrigin() {
83 MaybeLoadPrimaryOrigin();
84 if (primary_origin_database_
)
85 return primary_origin_database_
->origin();
89 bool SandboxPrioritizedOriginDatabase::HasOriginPath(
90 const std::string
& origin
) {
91 MaybeInitializeDatabases(false);
92 if (primary_origin_database_
&&
93 primary_origin_database_
->HasOriginPath(origin
))
96 return origin_database_
->HasOriginPath(origin
);
100 bool SandboxPrioritizedOriginDatabase::GetPathForOrigin(
101 const std::string
& origin
, base::FilePath
* directory
) {
102 MaybeInitializeDatabases(true);
103 if (primary_origin_database_
&&
104 primary_origin_database_
->GetPathForOrigin(origin
, directory
))
106 DCHECK(origin_database_
);
107 return origin_database_
->GetPathForOrigin(origin
, directory
);
110 bool SandboxPrioritizedOriginDatabase::RemovePathForOrigin(
111 const std::string
& origin
) {
112 MaybeInitializeDatabases(false);
113 if (primary_origin_database_
&&
114 primary_origin_database_
->HasOriginPath(origin
)) {
115 primary_origin_database_
.reset();
116 base::DeleteFile(file_system_directory_
.Append(kPrimaryOriginFile
),
117 true /* recursive */);
120 if (origin_database_
)
121 return origin_database_
->RemovePathForOrigin(origin
);
125 bool SandboxPrioritizedOriginDatabase::ListAllOrigins(
126 std::vector
<OriginRecord
>* origins
) {
127 // SandboxOriginDatabase may clear the |origins|, so call this before
128 // primary_origin_database_.
129 MaybeInitializeDatabases(false);
130 if (origin_database_
&& !origin_database_
->ListAllOrigins(origins
))
132 if (primary_origin_database_
)
133 return primary_origin_database_
->ListAllOrigins(origins
);
137 void SandboxPrioritizedOriginDatabase::DropDatabase() {
138 primary_origin_database_
.reset();
139 origin_database_
.reset();
142 bool SandboxPrioritizedOriginDatabase::MaybeLoadPrimaryOrigin() {
143 if (primary_origin_database_
)
145 std::string saved_origin
;
146 if (!ReadPrimaryOriginFile(primary_origin_file_
, &saved_origin
))
148 primary_origin_database_
.reset(
149 new SandboxIsolatedOriginDatabase(
151 file_system_directory_
,
152 base::FilePath(kPrimaryDirectory
)));
156 bool SandboxPrioritizedOriginDatabase::ResetPrimaryOrigin(
157 const std::string
& origin
) {
158 DCHECK(!primary_origin_database_
);
159 if (!WritePrimaryOriginFile(primary_origin_file_
, origin
))
161 // We reset the primary origin directory too.
162 // (This means the origin file corruption causes data loss
163 // We could keep the directory there as the same origin will likely
164 // become the primary origin, but let's play conservatively.)
165 base::DeleteFile(file_system_directory_
.Append(kPrimaryDirectory
),
166 true /* recursive */);
170 void SandboxPrioritizedOriginDatabase::MaybeMigrateDatabase(
171 const std::string
& origin
) {
172 MaybeInitializeNonPrimaryDatabase(false);
173 if (!origin_database_
)
175 if (origin_database_
->HasOriginPath(origin
)) {
176 base::FilePath directory_name
;
177 if (origin_database_
->GetPathForOrigin(origin
, &directory_name
) &&
178 directory_name
!= base::FilePath(kPrimaryOriginFile
)) {
179 base::FilePath from_path
= file_system_directory_
.Append(directory_name
);
180 base::FilePath to_path
= file_system_directory_
.Append(kPrimaryDirectory
);
182 if (base::PathExists(to_path
))
183 base::DeleteFile(to_path
, true /* recursive */);
184 base::Move(from_path
, to_path
);
187 origin_database_
->RemovePathForOrigin(origin
);
190 std::vector
<OriginRecord
> origins
;
191 origin_database_
->ListAllOrigins(&origins
);
192 if (origins
.empty()) {
193 origin_database_
->RemoveDatabase();
194 origin_database_
.reset();
198 void SandboxPrioritizedOriginDatabase::MaybeInitializeDatabases(
200 MaybeLoadPrimaryOrigin();
201 MaybeInitializeNonPrimaryDatabase(create
);
204 void SandboxPrioritizedOriginDatabase::MaybeInitializeNonPrimaryDatabase(
206 if (origin_database_
)
209 origin_database_
.reset(new SandboxOriginDatabase(file_system_directory_
,
211 if (!create
&& !base::DirectoryExists(origin_database_
->GetDatabasePath())) {
212 origin_database_
.reset();
217 SandboxOriginDatabase
*
218 SandboxPrioritizedOriginDatabase::GetSandboxOriginDatabase() {
219 MaybeInitializeNonPrimaryDatabase(true);
220 return origin_database_
.get();
223 } // namespace storage