Add entry to histograms.xml for OverlyLargeOriginLength.
[chromium-blink-merge.git] / webkit / browser / fileapi / sandbox_prioritized_origin_database.cc
blob06a44a07080362a68d18d86d57903f482cbb6513
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"
16 namespace fileapi {
18 namespace {
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;
28 bool created;
29 base::PlatformFile file = base::CreatePlatformFile(
30 path,
31 base::PLATFORM_FILE_OPEN_ALWAYS |
32 base::PLATFORM_FILE_WRITE,
33 &created, &error);
34 base::ScopedPlatformFileCloser closer(&file);
35 if (error != base::PLATFORM_FILE_OK ||
36 file == base::kInvalidPlatformFileValue)
37 return false;
38 base::TruncatePlatformFile(file, 0);
39 Pickle pickle;
40 pickle.WriteString(origin);
41 base::WritePlatformFile(file, 0, static_cast<const char*>(pickle.data()),
42 pickle.size());
43 base::FlushPlatformFile(file);
44 return true;
47 bool ReadPrimaryOriginFile(const base::FilePath& path,
48 std::string* origin) {
49 std::string buffer;
50 if (!base::ReadFileToString(path, &buffer))
51 return false;
52 Pickle pickle(buffer.data(), buffer.size());
53 PickleIterator iter(pickle);
54 return pickle.ReadString(&iter, origin) && !origin->empty();
57 } // namespace
59 SandboxPrioritizedOriginDatabase::SandboxPrioritizedOriginDatabase(
60 const base::FilePath& file_system_directory)
61 : file_system_directory_(file_system_directory),
62 primary_origin_file_(
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(
76 origin,
77 file_system_directory_,
78 base::FilePath(kPrimaryDirectory)));
79 return true;
83 if (primary_origin_database_)
84 return primary_origin_database_->HasOriginPath(origin);
86 return false;
89 std::string SandboxPrioritizedOriginDatabase::GetPrimaryOrigin() {
90 MaybeLoadPrimaryOrigin();
91 if (primary_origin_database_)
92 return primary_origin_database_->origin();
93 return std::string();
96 bool SandboxPrioritizedOriginDatabase::HasOriginPath(
97 const std::string& origin) {
98 MaybeInitializeDatabases(false);
99 if (primary_origin_database_ &&
100 primary_origin_database_->HasOriginPath(origin))
101 return true;
102 if (origin_database_)
103 return origin_database_->HasOriginPath(origin);
104 return false;
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))
112 return true;
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 */);
125 return true;
127 if (origin_database_)
128 return origin_database_->RemovePathForOrigin(origin);
129 return true;
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))
138 return false;
139 if (primary_origin_database_)
140 return primary_origin_database_->ListAllOrigins(origins);
141 return true;
144 void SandboxPrioritizedOriginDatabase::DropDatabase() {
145 primary_origin_database_.reset();
146 origin_database_.reset();
149 bool SandboxPrioritizedOriginDatabase::MaybeLoadPrimaryOrigin() {
150 if (primary_origin_database_)
151 return true;
152 std::string saved_origin;
153 if (!ReadPrimaryOriginFile(primary_origin_file_, &saved_origin))
154 return false;
155 primary_origin_database_.reset(
156 new SandboxIsolatedOriginDatabase(
157 saved_origin,
158 file_system_directory_,
159 base::FilePath(kPrimaryDirectory)));
160 return true;
163 bool SandboxPrioritizedOriginDatabase::ResetPrimaryOrigin(
164 const std::string& origin) {
165 DCHECK(!primary_origin_database_);
166 if (!WritePrimaryOriginFile(primary_origin_file_, origin))
167 return false;
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 */);
174 return true;
177 void SandboxPrioritizedOriginDatabase::MaybeMigrateDatabase(
178 const std::string& origin) {
179 MaybeInitializeNonPrimaryDatabase(false);
180 if (!origin_database_)
181 return;
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(
206 bool create) {
207 MaybeLoadPrimaryOrigin();
208 MaybeInitializeNonPrimaryDatabase(create);
211 void SandboxPrioritizedOriginDatabase::MaybeInitializeNonPrimaryDatabase(
212 bool create) {
213 if (origin_database_)
214 return;
216 origin_database_.reset(new SandboxOriginDatabase(file_system_directory_));
217 if (!create && !base::DirectoryExists(origin_database_->GetDatabasePath())) {
218 origin_database_.reset();
219 return;
223 SandboxOriginDatabase*
224 SandboxPrioritizedOriginDatabase::GetSandboxOriginDatabase() {
225 MaybeInitializeNonPrimaryDatabase(true);
226 return origin_database_.get();
229 } // namespace fileapi