• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "webkit/browser/fileapi/sandbox_prioritized_origin_database.h"
6 
7 #include "base/file_util.h"
8 #include "base/files/file.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/pickle.h"
12 #include "webkit/browser/fileapi/sandbox_isolated_origin_database.h"
13 #include "webkit/browser/fileapi/sandbox_origin_database.h"
14 
15 namespace fileapi {
16 
17 namespace {
18 
19 const base::FilePath::CharType kPrimaryDirectory[] =
20     FILE_PATH_LITERAL("primary");
21 const base::FilePath::CharType kPrimaryOriginFile[] =
22     FILE_PATH_LITERAL("primary.origin");
23 
WritePrimaryOriginFile(const base::FilePath & path,const std::string & 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);
27   if (!file.IsValid())
28     return false;
29   if (!file.created())
30     file.SetLength(0);
31   Pickle pickle;
32   pickle.WriteString(origin);
33   file.Write(0, static_cast<const char*>(pickle.data()), pickle.size());
34   file.Flush();
35   return true;
36 }
37 
ReadPrimaryOriginFile(const base::FilePath & path,std::string * origin)38 bool ReadPrimaryOriginFile(const base::FilePath& path,
39                            std::string* origin) {
40   std::string buffer;
41   if (!base::ReadFileToString(path, &buffer))
42     return false;
43   Pickle pickle(buffer.data(), buffer.size());
44   PickleIterator iter(pickle);
45   return pickle.ReadString(&iter, origin) && !origin->empty();
46 }
47 
48 }  // namespace
49 
SandboxPrioritizedOriginDatabase(const base::FilePath & file_system_directory,leveldb::Env * env_override)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),
55       primary_origin_file_(
56           file_system_directory_.Append(kPrimaryOriginFile)) {
57 }
58 
~SandboxPrioritizedOriginDatabase()59 SandboxPrioritizedOriginDatabase::~SandboxPrioritizedOriginDatabase() {
60 }
61 
InitializePrimaryOrigin(const std::string & origin)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(
69               origin,
70               file_system_directory_,
71               base::FilePath(kPrimaryDirectory)));
72       return true;
73     }
74   }
75 
76   if (primary_origin_database_)
77     return primary_origin_database_->HasOriginPath(origin);
78 
79   return false;
80 }
81 
GetPrimaryOrigin()82 std::string SandboxPrioritizedOriginDatabase::GetPrimaryOrigin() {
83   MaybeLoadPrimaryOrigin();
84   if (primary_origin_database_)
85     return primary_origin_database_->origin();
86   return std::string();
87 }
88 
HasOriginPath(const std::string & origin)89 bool SandboxPrioritizedOriginDatabase::HasOriginPath(
90     const std::string& origin) {
91   MaybeInitializeDatabases(false);
92   if (primary_origin_database_ &&
93       primary_origin_database_->HasOriginPath(origin))
94     return true;
95   if (origin_database_)
96     return origin_database_->HasOriginPath(origin);
97   return false;
98 }
99 
GetPathForOrigin(const std::string & origin,base::FilePath * directory)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))
105     return true;
106   DCHECK(origin_database_);
107   return origin_database_->GetPathForOrigin(origin, directory);
108 }
109 
RemovePathForOrigin(const std::string & origin)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 */);
118     return true;
119   }
120   if (origin_database_)
121     return origin_database_->RemovePathForOrigin(origin);
122   return true;
123 }
124 
ListAllOrigins(std::vector<OriginRecord> * origins)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))
131     return false;
132   if (primary_origin_database_)
133     return primary_origin_database_->ListAllOrigins(origins);
134   return true;
135 }
136 
DropDatabase()137 void SandboxPrioritizedOriginDatabase::DropDatabase() {
138   primary_origin_database_.reset();
139   origin_database_.reset();
140 }
141 
MaybeLoadPrimaryOrigin()142 bool SandboxPrioritizedOriginDatabase::MaybeLoadPrimaryOrigin() {
143   if (primary_origin_database_)
144     return true;
145   std::string saved_origin;
146   if (!ReadPrimaryOriginFile(primary_origin_file_, &saved_origin))
147     return false;
148   primary_origin_database_.reset(
149       new SandboxIsolatedOriginDatabase(
150           saved_origin,
151           file_system_directory_,
152           base::FilePath(kPrimaryDirectory)));
153   return true;
154 }
155 
ResetPrimaryOrigin(const std::string & origin)156 bool SandboxPrioritizedOriginDatabase::ResetPrimaryOrigin(
157     const std::string& origin) {
158   DCHECK(!primary_origin_database_);
159   if (!WritePrimaryOriginFile(primary_origin_file_, origin))
160     return false;
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 */);
167   return true;
168 }
169 
MaybeMigrateDatabase(const std::string & origin)170 void SandboxPrioritizedOriginDatabase::MaybeMigrateDatabase(
171     const std::string& origin) {
172   MaybeInitializeNonPrimaryDatabase(false);
173   if (!origin_database_)
174     return;
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);
181 
182       if (base::PathExists(to_path))
183         base::DeleteFile(to_path, true /* recursive */);
184       base::Move(from_path, to_path);
185     }
186 
187     origin_database_->RemovePathForOrigin(origin);
188   }
189 
190   std::vector<OriginRecord> origins;
191   origin_database_->ListAllOrigins(&origins);
192   if (origins.empty()) {
193     origin_database_->RemoveDatabase();
194     origin_database_.reset();
195   }
196 }
197 
MaybeInitializeDatabases(bool create)198 void SandboxPrioritizedOriginDatabase::MaybeInitializeDatabases(
199     bool create) {
200   MaybeLoadPrimaryOrigin();
201   MaybeInitializeNonPrimaryDatabase(create);
202 }
203 
MaybeInitializeNonPrimaryDatabase(bool create)204 void SandboxPrioritizedOriginDatabase::MaybeInitializeNonPrimaryDatabase(
205     bool create) {
206   if (origin_database_)
207     return;
208 
209   origin_database_.reset(new SandboxOriginDatabase(file_system_directory_,
210                                                    env_override_));
211   if (!create && !base::DirectoryExists(origin_database_->GetDatabasePath())) {
212     origin_database_.reset();
213     return;
214   }
215 }
216 
217 SandboxOriginDatabase*
GetSandboxOriginDatabase()218 SandboxPrioritizedOriginDatabase::GetSandboxOriginDatabase() {
219   MaybeInitializeNonPrimaryDatabase(true);
220   return origin_database_.get();
221 }
222 
223 }  // namespace fileapi
224