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 "webkit/browser/fileapi/sandbox_prioritized_origin_database.h"
7 #include "base/file_util.h"
8 #include "base/files/file_path.h"
9 #include "base/files/scoped_platform_file_closer.h"
10 #include "base/logging.h"
11 #include "base/pickle.h"
12 #include "base/platform_file.h"
13 #include "webkit/browser/fileapi/sandbox_isolated_origin_database.h"
14 #include "webkit/browser/fileapi/sandbox_origin_database.h"
20 const base::FilePath::CharType kPrimaryDirectory
[] =
21 FILE_PATH_LITERAL("primary");
22 const base::FilePath::CharType kPrimaryOriginFile
[] =
23 FILE_PATH_LITERAL("primary.origin");
25 bool WritePrimaryOriginFile(const base::FilePath
& path
,
26 const std::string
& origin
) {
27 base::PlatformFileError error
= base::PLATFORM_FILE_ERROR_FAILED
;
29 base::PlatformFile file
= base::CreatePlatformFile(
31 base::PLATFORM_FILE_OPEN_ALWAYS
|
32 base::PLATFORM_FILE_WRITE
,
34 base::ScopedPlatformFileCloser
closer(&file
);
35 if (error
!= base::PLATFORM_FILE_OK
||
36 file
== base::kInvalidPlatformFileValue
)
38 base::TruncatePlatformFile(file
, 0);
40 pickle
.WriteString(origin
);
41 base::WritePlatformFile(file
, 0, static_cast<const char*>(pickle
.data()),
43 base::FlushPlatformFile(file
);
47 bool ReadPrimaryOriginFile(const base::FilePath
& path
,
48 std::string
* origin
) {
50 if (!base::ReadFileToString(path
, &buffer
))
52 Pickle
pickle(buffer
.data(), buffer
.size());
53 PickleIterator
iter(pickle
);
54 return pickle
.ReadString(&iter
, origin
) && !origin
->empty();
59 SandboxPrioritizedOriginDatabase::SandboxPrioritizedOriginDatabase(
60 const base::FilePath
& file_system_directory
)
61 : file_system_directory_(file_system_directory
),
63 file_system_directory_
.Append(kPrimaryOriginFile
)) {
66 SandboxPrioritizedOriginDatabase::~SandboxPrioritizedOriginDatabase() {
69 bool SandboxPrioritizedOriginDatabase::InitializePrimaryOrigin(
70 const std::string
& origin
) {
71 if (!primary_origin_database_
) {
72 if (!MaybeLoadPrimaryOrigin() && ResetPrimaryOrigin(origin
)) {
73 MaybeMigrateDatabase(origin
);
74 primary_origin_database_
.reset(
75 new SandboxIsolatedOriginDatabase(
77 file_system_directory_
,
78 base::FilePath(kPrimaryDirectory
)));
83 if (primary_origin_database_
)
84 return primary_origin_database_
->HasOriginPath(origin
);
89 std::string
SandboxPrioritizedOriginDatabase::GetPrimaryOrigin() {
90 MaybeLoadPrimaryOrigin();
91 if (primary_origin_database_
)
92 return primary_origin_database_
->origin();
96 bool SandboxPrioritizedOriginDatabase::HasOriginPath(
97 const std::string
& origin
) {
98 MaybeInitializeDatabases(false);
99 if (primary_origin_database_
&&
100 primary_origin_database_
->HasOriginPath(origin
))
102 if (origin_database_
)
103 return origin_database_
->HasOriginPath(origin
);
107 bool SandboxPrioritizedOriginDatabase::GetPathForOrigin(
108 const std::string
& origin
, base::FilePath
* directory
) {
109 MaybeInitializeDatabases(true);
110 if (primary_origin_database_
&&
111 primary_origin_database_
->GetPathForOrigin(origin
, directory
))
113 DCHECK(origin_database_
);
114 return origin_database_
->GetPathForOrigin(origin
, directory
);
117 bool SandboxPrioritizedOriginDatabase::RemovePathForOrigin(
118 const std::string
& origin
) {
119 MaybeInitializeDatabases(false);
120 if (primary_origin_database_
&&
121 primary_origin_database_
->HasOriginPath(origin
)) {
122 primary_origin_database_
.reset();
123 base::DeleteFile(file_system_directory_
.Append(kPrimaryOriginFile
),
124 true /* recursive */);
127 if (origin_database_
)
128 return origin_database_
->RemovePathForOrigin(origin
);
132 bool SandboxPrioritizedOriginDatabase::ListAllOrigins(
133 std::vector
<OriginRecord
>* origins
) {
134 // SandboxOriginDatabase may clear the |origins|, so call this before
135 // primary_origin_database_.
136 MaybeInitializeDatabases(false);
137 if (origin_database_
&& !origin_database_
->ListAllOrigins(origins
))
139 if (primary_origin_database_
)
140 return primary_origin_database_
->ListAllOrigins(origins
);
144 void SandboxPrioritizedOriginDatabase::DropDatabase() {
145 primary_origin_database_
.reset();
146 origin_database_
.reset();
149 bool SandboxPrioritizedOriginDatabase::MaybeLoadPrimaryOrigin() {
150 if (primary_origin_database_
)
152 std::string saved_origin
;
153 if (!ReadPrimaryOriginFile(primary_origin_file_
, &saved_origin
))
155 primary_origin_database_
.reset(
156 new SandboxIsolatedOriginDatabase(
158 file_system_directory_
,
159 base::FilePath(kPrimaryDirectory
)));
163 bool SandboxPrioritizedOriginDatabase::ResetPrimaryOrigin(
164 const std::string
& origin
) {
165 DCHECK(!primary_origin_database_
);
166 if (!WritePrimaryOriginFile(primary_origin_file_
, origin
))
168 // We reset the primary origin directory too.
169 // (This means the origin file corruption causes data loss
170 // We could keep the directory there as the same origin will likely
171 // become the primary origin, but let's play conservatively.)
172 base::DeleteFile(file_system_directory_
.Append(kPrimaryDirectory
),
173 true /* recursive */);
177 void SandboxPrioritizedOriginDatabase::MaybeMigrateDatabase(
178 const std::string
& origin
) {
179 MaybeInitializeNonPrimaryDatabase(false);
180 if (!origin_database_
)
182 if (origin_database_
->HasOriginPath(origin
)) {
183 base::FilePath directory_name
;
184 if (origin_database_
->GetPathForOrigin(origin
, &directory_name
) &&
185 directory_name
!= base::FilePath(kPrimaryOriginFile
)) {
186 base::FilePath from_path
= file_system_directory_
.Append(directory_name
);
187 base::FilePath to_path
= file_system_directory_
.Append(kPrimaryDirectory
);
189 if (base::PathExists(to_path
))
190 base::DeleteFile(to_path
, true /* recursive */);
191 base::Move(from_path
, to_path
);
194 origin_database_
->RemovePathForOrigin(origin
);
197 std::vector
<OriginRecord
> origins
;
198 origin_database_
->ListAllOrigins(&origins
);
199 if (origins
.empty()) {
200 origin_database_
->RemoveDatabase();
201 origin_database_
.reset();
205 void SandboxPrioritizedOriginDatabase::MaybeInitializeDatabases(
207 MaybeLoadPrimaryOrigin();
208 MaybeInitializeNonPrimaryDatabase(create
);
211 void SandboxPrioritizedOriginDatabase::MaybeInitializeNonPrimaryDatabase(
213 if (origin_database_
)
216 origin_database_
.reset(new SandboxOriginDatabase(file_system_directory_
));
217 if (!create
&& !base::DirectoryExists(origin_database_
->GetDatabasePath())) {
218 origin_database_
.reset();
223 SandboxOriginDatabase
*
224 SandboxPrioritizedOriginDatabase::GetSandboxOriginDatabase() {
225 MaybeInitializeNonPrimaryDatabase(true);
226 return origin_database_
.get();
229 } // namespace fileapi