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_util.h"
9 #include "base/logging.h"
10 #include "base/pickle.h"
11 #include "storage/browser/fileapi/sandbox_isolated_origin_database.h"
12 #include "storage/browser/fileapi/sandbox_origin_database.h"
16 const base::FilePath::CharType
*
17 SandboxPrioritizedOriginDatabase::kPrimaryDirectory
=
18 FILE_PATH_LITERAL("primary");
20 const base::FilePath::CharType
*
21 SandboxPrioritizedOriginDatabase::kPrimaryOriginFile
=
22 FILE_PATH_LITERAL("primary.origin");
26 bool WritePrimaryOriginFile(const base::FilePath
& path
,
27 const std::string
& origin
) {
28 base::File
file(path
, base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_WRITE
);
34 pickle
.WriteString(origin
);
35 file
.Write(0, static_cast<const char*>(pickle
.data()), pickle
.size());
40 bool ReadPrimaryOriginFile(const base::FilePath
& path
,
41 std::string
* origin
) {
43 if (!base::ReadFileToString(path
, &buffer
))
45 Pickle
pickle(buffer
.data(), buffer
.size());
46 PickleIterator
iter(pickle
);
47 return pickle
.ReadString(&iter
, origin
) && !origin
->empty();
52 SandboxPrioritizedOriginDatabase::SandboxPrioritizedOriginDatabase(
53 const base::FilePath
& file_system_directory
,
54 leveldb::Env
* env_override
)
55 : file_system_directory_(file_system_directory
),
56 env_override_(env_override
),
58 file_system_directory_
.Append(kPrimaryOriginFile
)) {
61 SandboxPrioritizedOriginDatabase::~SandboxPrioritizedOriginDatabase() {
64 bool SandboxPrioritizedOriginDatabase::InitializePrimaryOrigin(
65 const std::string
& origin
) {
66 if (!primary_origin_database_
) {
67 if (!MaybeLoadPrimaryOrigin() && ResetPrimaryOrigin(origin
)) {
68 MaybeMigrateDatabase(origin
);
69 primary_origin_database_
.reset(
70 new SandboxIsolatedOriginDatabase(
72 file_system_directory_
,
73 base::FilePath(kPrimaryDirectory
)));
78 if (primary_origin_database_
)
79 return primary_origin_database_
->HasOriginPath(origin
);
84 std::string
SandboxPrioritizedOriginDatabase::GetPrimaryOrigin() {
85 MaybeLoadPrimaryOrigin();
86 if (primary_origin_database_
)
87 return primary_origin_database_
->origin();
91 bool SandboxPrioritizedOriginDatabase::HasOriginPath(
92 const std::string
& origin
) {
93 MaybeInitializeDatabases(false);
94 if (primary_origin_database_
&&
95 primary_origin_database_
->HasOriginPath(origin
))
98 return origin_database_
->HasOriginPath(origin
);
102 bool SandboxPrioritizedOriginDatabase::GetPathForOrigin(
103 const std::string
& origin
, base::FilePath
* directory
) {
104 MaybeInitializeDatabases(true);
105 if (primary_origin_database_
&&
106 primary_origin_database_
->GetPathForOrigin(origin
, directory
))
108 DCHECK(origin_database_
);
109 return origin_database_
->GetPathForOrigin(origin
, directory
);
112 bool SandboxPrioritizedOriginDatabase::RemovePathForOrigin(
113 const std::string
& origin
) {
114 MaybeInitializeDatabases(false);
115 if (primary_origin_database_
&&
116 primary_origin_database_
->HasOriginPath(origin
)) {
117 primary_origin_database_
.reset();
118 base::DeleteFile(file_system_directory_
.Append(kPrimaryOriginFile
),
119 true /* recursive */);
122 if (origin_database_
)
123 return origin_database_
->RemovePathForOrigin(origin
);
127 bool SandboxPrioritizedOriginDatabase::ListAllOrigins(
128 std::vector
<OriginRecord
>* origins
) {
129 // SandboxOriginDatabase may clear the |origins|, so call this before
130 // primary_origin_database_.
131 MaybeInitializeDatabases(false);
132 if (origin_database_
&& !origin_database_
->ListAllOrigins(origins
))
134 if (primary_origin_database_
)
135 return primary_origin_database_
->ListAllOrigins(origins
);
139 void SandboxPrioritizedOriginDatabase::DropDatabase() {
140 primary_origin_database_
.reset();
141 origin_database_
.reset();
144 bool SandboxPrioritizedOriginDatabase::MaybeLoadPrimaryOrigin() {
145 if (primary_origin_database_
)
147 std::string saved_origin
;
148 if (!ReadPrimaryOriginFile(primary_origin_file_
, &saved_origin
))
150 primary_origin_database_
.reset(
151 new SandboxIsolatedOriginDatabase(
153 file_system_directory_
,
154 base::FilePath(kPrimaryDirectory
)));
158 bool SandboxPrioritizedOriginDatabase::ResetPrimaryOrigin(
159 const std::string
& origin
) {
160 DCHECK(!primary_origin_database_
);
161 if (!WritePrimaryOriginFile(primary_origin_file_
, origin
))
163 // We reset the primary origin directory too.
164 // (This means the origin file corruption causes data loss
165 // We could keep the directory there as the same origin will likely
166 // become the primary origin, but let's play conservatively.)
167 base::DeleteFile(file_system_directory_
.Append(kPrimaryDirectory
),
168 true /* recursive */);
172 void SandboxPrioritizedOriginDatabase::MaybeMigrateDatabase(
173 const std::string
& origin
) {
174 MaybeInitializeNonPrimaryDatabase(false);
175 if (!origin_database_
)
177 if (origin_database_
->HasOriginPath(origin
)) {
178 base::FilePath directory_name
;
179 if (origin_database_
->GetPathForOrigin(origin
, &directory_name
) &&
180 directory_name
!= base::FilePath(kPrimaryOriginFile
)) {
181 base::FilePath from_path
= file_system_directory_
.Append(directory_name
);
182 base::FilePath to_path
= file_system_directory_
.Append(kPrimaryDirectory
);
184 if (base::PathExists(to_path
))
185 base::DeleteFile(to_path
, true /* recursive */);
186 base::Move(from_path
, to_path
);
189 origin_database_
->RemovePathForOrigin(origin
);
192 std::vector
<OriginRecord
> origins
;
193 origin_database_
->ListAllOrigins(&origins
);
194 if (origins
.empty()) {
195 origin_database_
->RemoveDatabase();
196 origin_database_
.reset();
200 void SandboxPrioritizedOriginDatabase::MaybeInitializeDatabases(
202 MaybeLoadPrimaryOrigin();
203 MaybeInitializeNonPrimaryDatabase(create
);
206 void SandboxPrioritizedOriginDatabase::MaybeInitializeNonPrimaryDatabase(
208 if (origin_database_
)
211 origin_database_
.reset(new SandboxOriginDatabase(file_system_directory_
,
213 if (!create
&& !base::DirectoryExists(origin_database_
->GetDatabasePath())) {
214 origin_database_
.reset();
219 SandboxOriginDatabase
*
220 SandboxPrioritizedOriginDatabase::GetSandboxOriginDatabase() {
221 MaybeInitializeNonPrimaryDatabase(true);
222 return origin_database_
.get();
225 } // namespace storage