OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/fileapi/sandbox_mount_point_provider.h" | 5 #include "webkit/fileapi/sandbox_mount_point_provider.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
12 #include "base/message_loop_proxy.h" | 12 #include "base/message_loop_proxy.h" |
13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
15 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
17 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
18 #include "net/base/net_util.h" | 18 #include "net/base/net_util.h" |
| 19 #include "webkit/fileapi/file_system_operation.h" |
19 #include "webkit/fileapi/file_system_operation_context.h" | 20 #include "webkit/fileapi/file_system_operation_context.h" |
20 #include "webkit/fileapi/file_system_options.h" | 21 #include "webkit/fileapi/file_system_options.h" |
21 #include "webkit/fileapi/file_system_types.h" | 22 #include "webkit/fileapi/file_system_types.h" |
22 #include "webkit/fileapi/file_system_usage_cache.h" | 23 #include "webkit/fileapi/file_system_usage_cache.h" |
23 #include "webkit/fileapi/file_system_util.h" | 24 #include "webkit/fileapi/file_system_util.h" |
24 #include "webkit/fileapi/obfuscated_file_util.h" | 25 #include "webkit/fileapi/obfuscated_file_util.h" |
25 #include "webkit/fileapi/quota_file_util.h" | 26 #include "webkit/fileapi/quota_file_util.h" |
26 #include "webkit/glue/webkit_glue.h" | 27 #include "webkit/glue/webkit_glue.h" |
27 #include "webkit/quota/quota_manager.h" | 28 #include "webkit/quota/quota_manager.h" |
28 | 29 |
29 using quota::QuotaManagerProxy; | 30 using quota::QuotaManagerProxy; |
30 | 31 |
| 32 namespace fileapi { |
| 33 |
31 namespace { | 34 namespace { |
32 | 35 |
33 const char kChromeScheme[] = "chrome"; | 36 const char kChromeScheme[] = "chrome"; |
34 const char kExtensionScheme[] = "chrome-extension"; | 37 const char kExtensionScheme[] = "chrome-extension"; |
35 | 38 |
36 const FilePath::CharType kOldFileSystemUniqueNamePrefix[] = | 39 const FilePath::CharType kOldFileSystemUniqueNamePrefix[] = |
37 FILE_PATH_LITERAL("chrome-"); | 40 FILE_PATH_LITERAL("chrome-"); |
38 const size_t kOldFileSystemUniqueLength = 16; | 41 const size_t kOldFileSystemUniqueLength = 16; |
39 const size_t kOldFileSystemUniqueDirectoryNameLength = | 42 const size_t kOldFileSystemUniqueDirectoryNameLength = |
40 kOldFileSystemUniqueLength + arraysize(kOldFileSystemUniqueNamePrefix) - 1; | 43 kOldFileSystemUniqueLength + arraysize(kOldFileSystemUniqueNamePrefix) - 1; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 } | 92 } |
90 found = true; | 93 found = true; |
91 *unique = current; | 94 *unique = current; |
92 } | 95 } |
93 if (unique->empty()) | 96 if (unique->empty()) |
94 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 97 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
95 return base::PLATFORM_FILE_OK; | 98 return base::PLATFORM_FILE_OK; |
96 } | 99 } |
97 | 100 |
98 class ObfuscatedOriginEnumerator | 101 class ObfuscatedOriginEnumerator |
99 : public fileapi::SandboxMountPointProvider::OriginEnumerator { | 102 : public SandboxMountPointProvider::OriginEnumerator { |
100 public: | 103 public: |
101 explicit ObfuscatedOriginEnumerator( | 104 explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) { |
102 fileapi::ObfuscatedFileUtil* file_util) { | |
103 enum_.reset(file_util->CreateOriginEnumerator()); | 105 enum_.reset(file_util->CreateOriginEnumerator()); |
104 } | 106 } |
105 virtual ~ObfuscatedOriginEnumerator() {} | 107 virtual ~ObfuscatedOriginEnumerator() {} |
106 | 108 |
107 virtual GURL Next() OVERRIDE { | 109 virtual GURL Next() OVERRIDE { |
108 return enum_->Next(); | 110 return enum_->Next(); |
109 } | 111 } |
110 | 112 |
111 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { | 113 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { |
112 return enum_->HasFileSystemType(type); | 114 return enum_->HasFileSystemType(type); |
113 } | 115 } |
114 | 116 |
115 private: | 117 private: |
116 scoped_ptr<fileapi::ObfuscatedFileUtil::AbstractOriginEnumerator> enum_; | 118 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_; |
117 }; | 119 }; |
118 | 120 |
119 class OldSandboxOriginEnumerator | 121 class OldSandboxOriginEnumerator |
120 : public fileapi::SandboxMountPointProvider::OriginEnumerator { | 122 : public SandboxMountPointProvider::OriginEnumerator { |
121 public: | 123 public: |
122 explicit OldSandboxOriginEnumerator(const FilePath& base_path) | 124 explicit OldSandboxOriginEnumerator(const FilePath& base_path) |
123 : enumerator_(base_path, false /* recursive */, | 125 : enumerator_(base_path, false /* recursive */, |
124 file_util::FileEnumerator::DIRECTORIES) {} | 126 file_util::FileEnumerator::DIRECTORIES) {} |
125 virtual ~OldSandboxOriginEnumerator() {} | 127 virtual ~OldSandboxOriginEnumerator() {} |
126 | 128 |
127 virtual GURL Next() OVERRIDE { | 129 virtual GURL Next() OVERRIDE { |
128 current_ = enumerator_.Next(); | 130 current_ = enumerator_.Next(); |
129 if (current_.empty()) | 131 if (current_.empty()) |
130 return GURL(); | 132 return GURL(); |
131 return fileapi::GetOriginURLFromIdentifier( | 133 return GetOriginURLFromIdentifier(current_.BaseName().MaybeAsASCII()); |
132 current_.BaseName().MaybeAsASCII()); | |
133 } | 134 } |
134 | 135 |
135 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { | 136 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { |
136 if (current_.empty()) | 137 if (current_.empty()) |
137 return false; | 138 return false; |
138 std::string directory = GetFileSystemTypeString(type); | 139 std::string directory = GetFileSystemTypeString(type); |
139 DCHECK(!directory.empty()); | 140 DCHECK(!directory.empty()); |
140 return file_util::DirectoryExists(current_.AppendASCII(directory)); | 141 return file_util::DirectoryExists(current_.AppendASCII(directory)); |
141 } | 142 } |
142 | 143 |
143 private: | 144 private: |
144 file_util::FileEnumerator enumerator_; | 145 file_util::FileEnumerator enumerator_; |
145 FilePath current_; | 146 FilePath current_; |
146 }; | 147 }; |
147 | 148 |
148 FilePath OldGetBaseDirectoryForOrigin( | 149 FilePath OldGetBaseDirectoryForOrigin( |
149 const FilePath& old_base_path, | 150 const FilePath& old_base_path, |
150 const GURL& origin_url) { | 151 const GURL& origin_url) { |
151 std::string id = fileapi::GetOriginIdentifierFromURL(origin_url); | 152 std::string id = GetOriginIdentifierFromURL(origin_url); |
152 if (!id.empty()) | 153 if (!id.empty()) |
153 return old_base_path.AppendASCII(id); | 154 return old_base_path.AppendASCII(id); |
154 return FilePath(); | 155 return FilePath(); |
155 } | 156 } |
156 | 157 |
157 FilePath OldGetBaseDirectoryForOriginAndType( | 158 FilePath OldGetBaseDirectoryForOriginAndType( |
158 const FilePath& old_base_path, | 159 const FilePath& old_base_path, |
159 const GURL& origin_url, fileapi::FileSystemType type) { | 160 const GURL& origin_url, fileapi::FileSystemType type) { |
160 std::string type_string = GetFileSystemTypeString(type); | 161 std::string type_string = GetFileSystemTypeString(type); |
161 if (type_string.empty()) { | 162 if (type_string.empty()) { |
162 NOTREACHED(); | 163 NOTREACHED(); |
163 return FilePath(); | 164 return FilePath(); |
164 } | 165 } |
165 FilePath base_path = OldGetBaseDirectoryForOrigin( | 166 FilePath base_path = OldGetBaseDirectoryForOrigin( |
166 old_base_path, origin_url); | 167 old_base_path, origin_url); |
167 if (base_path.empty()) { | 168 if (base_path.empty()) { |
168 NOTREACHED(); | 169 NOTREACHED(); |
169 return FilePath(); | 170 return FilePath(); |
170 } | 171 } |
171 return base_path.AppendASCII(type_string); | 172 return base_path.AppendASCII(type_string); |
172 } | 173 } |
173 | 174 |
174 bool MigrateOneOldFileSystem( | 175 bool MigrateOneOldFileSystem( |
175 fileapi::ObfuscatedFileUtil* file_util, | 176 ObfuscatedFileUtil* file_util, |
176 const FilePath& old_base_path, const GURL& origin, | 177 const FilePath& old_base_path, const GURL& origin, |
177 fileapi::FileSystemType type) { | 178 fileapi::FileSystemType type) { |
178 FilePath base_path = OldGetBaseDirectoryForOriginAndType( | 179 FilePath base_path = OldGetBaseDirectoryForOriginAndType( |
179 old_base_path, origin, type); | 180 old_base_path, origin, type); |
180 if (base_path.empty()) | 181 if (base_path.empty()) |
181 return false; | 182 return false; |
182 | 183 |
183 FilePath root; | 184 FilePath root; |
184 base::PlatformFileError result = OldReadOriginDirectory(base_path, &root); | 185 base::PlatformFileError result = OldReadOriginDirectory(base_path, &root); |
185 if (base::PLATFORM_FILE_ERROR_NOT_FOUND == result) | 186 if (base::PLATFORM_FILE_ERROR_NOT_FOUND == result) |
186 return true; // There was nothing to migrate; call that a success. | 187 return true; // There was nothing to migrate; call that a success. |
187 | 188 |
188 // If we found more than one filesystem [a problem we don't know how to | 189 // If we found more than one filesystem [a problem we don't know how to |
189 // solve], the data is already not accessible through Chrome, so it won't do | 190 // solve], the data is already not accessible through Chrome, so it won't do |
190 // any harm not to migrate it. Just flag it as an error, so that we don't | 191 // any harm not to migrate it. Just flag it as an error, so that we don't |
191 // delete it. | 192 // delete it. |
192 if (base::PLATFORM_FILE_OK != result) | 193 if (base::PLATFORM_FILE_OK != result) |
193 return false; | 194 return false; |
194 | 195 |
195 if (!file_util->MigrateFromOldSandbox(origin, type, root)) { | 196 if (!file_util->MigrateFromOldSandbox(origin, type, root)) { |
196 LOG(WARNING) << "Failed to migrate filesystem for origin " << origin << | 197 LOG(WARNING) << "Failed to migrate filesystem for origin " << origin << |
197 " and type " << type; | 198 " and type " << type; |
198 return false; | 199 return false; |
199 } | 200 } |
200 return true; | 201 return true; |
201 } | 202 } |
202 | 203 |
203 void MigrateAllOldFileSystems( | 204 void MigrateAllOldFileSystems( |
204 fileapi::ObfuscatedFileUtil* file_util, | 205 ObfuscatedFileUtil* file_util, |
205 const FilePath& old_base_path) { | 206 const FilePath& old_base_path) { |
206 scoped_ptr<OldSandboxOriginEnumerator> old_origins( | 207 scoped_ptr<OldSandboxOriginEnumerator> old_origins( |
207 new OldSandboxOriginEnumerator(old_base_path)); | 208 new OldSandboxOriginEnumerator(old_base_path)); |
208 GURL origin; | 209 GURL origin; |
209 int failures = 0; | 210 int failures = 0; |
210 while (!(origin = old_origins->Next()).is_empty()) { | 211 while (!(origin = old_origins->Next()).is_empty()) { |
211 int failures_this_origin = 0; | 212 int failures_this_origin = 0; |
212 if (old_origins->HasFileSystemType(fileapi::kFileSystemTypeTemporary) && | 213 if (old_origins->HasFileSystemType(kFileSystemTypeTemporary) && |
213 !MigrateOneOldFileSystem( | 214 !MigrateOneOldFileSystem( |
214 file_util, old_base_path, origin, | 215 file_util, old_base_path, origin, |
215 fileapi::kFileSystemTypeTemporary)) | 216 kFileSystemTypeTemporary)) |
216 ++failures_this_origin; | 217 ++failures_this_origin; |
217 if (old_origins->HasFileSystemType(fileapi::kFileSystemTypePersistent) && | 218 if (old_origins->HasFileSystemType(kFileSystemTypePersistent) && |
218 !MigrateOneOldFileSystem( | 219 !MigrateOneOldFileSystem( |
219 file_util, old_base_path, origin, | 220 file_util, old_base_path, origin, |
220 fileapi::kFileSystemTypePersistent)) | 221 kFileSystemTypePersistent)) |
221 ++failures_this_origin; | 222 ++failures_this_origin; |
222 if (!failures_this_origin) { | 223 if (!failures_this_origin) { |
223 FilePath origin_base_path = | 224 FilePath origin_base_path = |
224 OldGetBaseDirectoryForOrigin(old_base_path, origin); | 225 OldGetBaseDirectoryForOrigin(old_base_path, origin); |
225 // Yes, that's an rm -rf. Make sure that path looks valid, just in case. | 226 // Yes, that's an rm -rf. Make sure that path looks valid, just in case. |
226 if (!origin_base_path.empty()) | 227 if (!origin_base_path.empty()) |
227 file_util::Delete(origin_base_path, true); | 228 file_util::Delete(origin_base_path, true); |
228 } | 229 } |
229 failures += failures_this_origin; | 230 failures += failures_this_origin; |
230 } | 231 } |
231 if (!failures) | 232 if (!failures) |
232 file_util::Delete(old_base_path, true); | 233 file_util::Delete(old_base_path, true); |
233 if (file_util::DirectoryExists(old_base_path)) { | 234 if (file_util::DirectoryExists(old_base_path)) { |
234 // Move it out of the way so that we won't keep trying to migrate it. You | 235 // Move it out of the way so that we won't keep trying to migrate it. You |
235 // get only one chance at this; the bits we couldn't do this time, we're | 236 // get only one chance at this; the bits we couldn't do this time, we're |
236 // unlikely to be able to do in the future. This way you can now use the | 237 // unlikely to be able to do in the future. This way you can now use the |
237 // new filesystem, but have a way to recover your old files if absolutely | 238 // new filesystem, but have a way to recover your old files if absolutely |
238 // necessary. | 239 // necessary. |
239 FilePath new_path = | 240 FilePath new_path = |
240 old_base_path.DirName().Append( | 241 old_base_path.DirName().Append( |
241 fileapi::SandboxMountPointProvider::kRenamedOldFileSystemDirectory); | 242 SandboxMountPointProvider::kRenamedOldFileSystemDirectory); |
242 file_util::ReplaceFile(old_base_path, new_path); | 243 file_util::ReplaceFile(old_base_path, new_path); |
243 } | 244 } |
244 } | 245 } |
245 | 246 |
246 // A migration, whether successful or not, will try to move this directory out | 247 // A migration, whether successful or not, will try to move this directory out |
247 // of the way so that we never try to migrate it again. We need to do this | 248 // of the way so that we never try to migrate it again. We need to do this |
248 // check on all public entry points in this file, so that it's guaranteed to be | 249 // check on all public entry points in this file, so that it's guaranteed to be |
249 // done before anyone looks up a filesystem. Most entry points start by trying | 250 // done before anyone looks up a filesystem. Most entry points start by trying |
250 // to look up the filesystem's root, so we can take care of most of them by | 251 // to look up the filesystem's root, so we can take care of most of them by |
251 // putting a check there. | 252 // putting a check there. |
252 void MigrateIfNeeded( | 253 void MigrateIfNeeded( |
253 fileapi::ObfuscatedFileUtil* file_util, | 254 ObfuscatedFileUtil* file_util, |
254 const FilePath& old_base_path) { | 255 const FilePath& old_base_path) { |
255 if (file_util::DirectoryExists(old_base_path)) | 256 if (file_util::DirectoryExists(old_base_path)) |
256 MigrateAllOldFileSystems(file_util, old_base_path); | 257 MigrateAllOldFileSystems(file_util, old_base_path); |
257 } | 258 } |
258 | 259 |
| 260 void PassPointerErrorByValue( |
| 261 const base::Callback<void(PlatformFileError)>& callback, |
| 262 PlatformFileError* error_ptr) { |
| 263 DCHECK(error_ptr); |
| 264 callback.Run(*error_ptr); |
| 265 } |
| 266 |
| 267 void ValidateRootOnFileThread(ObfuscatedFileUtil* file_util, |
| 268 const GURL& origin_url, |
| 269 FileSystemType type, |
| 270 const FilePath& old_base_path, |
| 271 bool create, |
| 272 base::PlatformFileError* error_ptr) { |
| 273 DCHECK(error_ptr); |
| 274 MigrateIfNeeded(file_util, old_base_path); |
| 275 FilePath root_path = |
| 276 file_util->GetDirectoryForOriginAndType(origin_url, type, create); |
| 277 if (root_path.empty()) { |
| 278 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, |
| 279 kCreateDirectoryError, |
| 280 kFileSystemErrorMax); |
| 281 // TODO(kinuko): We should return appropriate error code. |
| 282 *error_ptr = base::PLATFORM_FILE_ERROR_FAILED; |
| 283 } else { |
| 284 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, kOK, kFileSystemErrorMax); |
| 285 *error_ptr = base::PLATFORM_FILE_OK; |
| 286 } |
| 287 // The reference of file_util will be derefed on the FILE thread |
| 288 // when the storage of this callback gets deleted regardless of whether |
| 289 // this method is called or not. |
| 290 } |
| 291 |
259 } // anonymous namespace | 292 } // anonymous namespace |
260 | 293 |
261 namespace fileapi { | |
262 | |
263 const FilePath::CharType SandboxMountPointProvider::kOldFileSystemDirectory[] = | 294 const FilePath::CharType SandboxMountPointProvider::kOldFileSystemDirectory[] = |
264 FILE_PATH_LITERAL("FileSystem"); | 295 FILE_PATH_LITERAL("FileSystem"); |
265 | 296 |
266 const FilePath::CharType SandboxMountPointProvider::kNewFileSystemDirectory[] = | 297 const FilePath::CharType SandboxMountPointProvider::kNewFileSystemDirectory[] = |
267 FILE_PATH_LITERAL("File System"); | 298 FILE_PATH_LITERAL("File System"); |
268 | 299 |
269 const FilePath::CharType | 300 const FilePath::CharType |
270 SandboxMountPointProvider::kRenamedOldFileSystemDirectory[] = | 301 SandboxMountPointProvider::kRenamedOldFileSystemDirectory[] = |
271 FILE_PATH_LITERAL("FS.old"); | 302 FILE_PATH_LITERAL("FS.old"); |
272 | 303 |
273 class SandboxMountPointProvider::GetFileSystemRootPathTask | |
274 : public base::RefCountedThreadSafe< | |
275 SandboxMountPointProvider::GetFileSystemRootPathTask> { | |
276 public: | |
277 GetFileSystemRootPathTask( | |
278 scoped_refptr<base::MessageLoopProxy> file_message_loop, | |
279 const GURL& origin_url, | |
280 FileSystemType type, | |
281 ObfuscatedFileUtil* file_util, | |
282 const FilePath& old_base_path, | |
283 const FileSystemMountPointProvider::GetRootPathCallback& callback) | |
284 : file_message_loop_(file_message_loop), | |
285 origin_message_loop_proxy_( | |
286 base::MessageLoopProxy::current()), | |
287 origin_url_(origin_url), | |
288 type_(type), | |
289 file_util_(file_util), | |
290 old_base_path_(old_base_path), | |
291 callback_(callback) { | |
292 } | |
293 | |
294 virtual ~GetFileSystemRootPathTask() { | |
295 // Just in case we get deleted without running, make sure to clean up the | |
296 // file_util_ on the right thread. | |
297 if (file_util_.get() && !file_message_loop_->BelongsToCurrentThread()) | |
298 file_message_loop_->ReleaseSoon(FROM_HERE, file_util_.release()); | |
299 } | |
300 | |
301 void Start(bool create) { | |
302 file_message_loop_->PostTask( | |
303 FROM_HERE, | |
304 base::Bind( | |
305 &GetFileSystemRootPathTask::GetFileSystemRootPathOnFileThread, this, | |
306 create)); | |
307 } | |
308 | |
309 private: | |
310 void GetFileSystemRootPathOnFileThread(bool create) { | |
311 MigrateIfNeeded(file_util_, old_base_path_); | |
312 DispatchCallbackOnCallerThread( | |
313 file_util_->GetDirectoryForOriginAndType(origin_url_, type_, create)); | |
314 // We must clear the reference on the file thread. | |
315 file_util_ = NULL; | |
316 } | |
317 | |
318 void DispatchCallbackOnCallerThread(const FilePath& root_path) { | |
319 if (root_path.empty()) { | |
320 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, | |
321 kCreateDirectoryError, | |
322 kFileSystemErrorMax); | |
323 } | |
324 origin_message_loop_proxy_->PostTask( | |
325 FROM_HERE, | |
326 base::Bind(&GetFileSystemRootPathTask::DispatchCallback, this, | |
327 root_path)); | |
328 } | |
329 | |
330 void DispatchCallback(const FilePath& root_path) { | |
331 std::string origin_identifier = GetOriginIdentifierFromURL(origin_url_); | |
332 std::string type_string = GetFileSystemTypeString(type_); | |
333 DCHECK(!type_string.empty()); | |
334 std::string name = origin_identifier + ":" + type_string; | |
335 | |
336 if (!root_path.empty()) | |
337 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, kOK, kFileSystemErrorMax); | |
338 | |
339 callback_.Run(!root_path.empty(), root_path, name); | |
340 callback_.Reset(); | |
341 } | |
342 | |
343 scoped_refptr<base::MessageLoopProxy> file_message_loop_; | |
344 scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_; | |
345 GURL origin_url_; | |
346 FileSystemType type_; | |
347 scoped_refptr<ObfuscatedFileUtil> file_util_; | |
348 FilePath old_base_path_; | |
349 FileSystemMountPointProvider::GetRootPathCallback callback_; | |
350 }; | |
351 | |
352 SandboxMountPointProvider::SandboxMountPointProvider( | 304 SandboxMountPointProvider::SandboxMountPointProvider( |
353 scoped_refptr<base::MessageLoopProxy> file_message_loop, | 305 scoped_refptr<base::MessageLoopProxy> file_message_loop, |
354 const FilePath& profile_path, | 306 const FilePath& profile_path, |
355 const FileSystemOptions& file_system_options) | 307 const FileSystemOptions& file_system_options) |
356 : FileSystemQuotaUtil(file_message_loop), | 308 : FileSystemQuotaUtil(file_message_loop), |
357 file_message_loop_(file_message_loop), | 309 file_message_loop_(file_message_loop), |
358 profile_path_(profile_path), | 310 profile_path_(profile_path), |
359 file_system_options_(file_system_options), | 311 file_system_options_(file_system_options), |
360 sandbox_file_util_( | 312 sandbox_file_util_( |
361 new ObfuscatedFileUtil( | 313 new ObfuscatedFileUtil( |
362 profile_path.Append(kNewFileSystemDirectory), | 314 profile_path.Append(kNewFileSystemDirectory), |
363 QuotaFileUtil::CreateDefault())) { | 315 QuotaFileUtil::CreateDefault())) { |
364 } | 316 } |
365 | 317 |
366 SandboxMountPointProvider::~SandboxMountPointProvider() { | 318 SandboxMountPointProvider::~SandboxMountPointProvider() { |
367 if (!file_message_loop_->BelongsToCurrentThread()) | 319 if (!file_message_loop_->BelongsToCurrentThread()) |
368 file_message_loop_->ReleaseSoon(FROM_HERE, sandbox_file_util_.release()); | 320 file_message_loop_->ReleaseSoon(FROM_HERE, sandbox_file_util_.release()); |
369 } | 321 } |
370 | 322 |
371 bool SandboxMountPointProvider::IsAccessAllowed(const GURL& origin_url, | 323 void SandboxMountPointProvider::ValidateFileSystemRoot( |
372 FileSystemType type, | |
373 const FilePath& unused) { | |
374 if (type != kFileSystemTypeTemporary && type != kFileSystemTypePersistent) | |
375 return false; | |
376 // We essentially depend on quota to do our access controls, so here | |
377 // we only check if the requested scheme is allowed or not. | |
378 return IsAllowedScheme(origin_url); | |
379 } | |
380 | |
381 void SandboxMountPointProvider::ValidateFileSystemRootAndGetURL( | |
382 const GURL& origin_url, fileapi::FileSystemType type, bool create, | 324 const GURL& origin_url, fileapi::FileSystemType type, bool create, |
383 const FileSystemMountPointProvider::GetRootPathCallback& callback) { | 325 const ValidateFileSystemCallback& callback) { |
384 FilePath origin_base_path; | |
385 | |
386 if (file_system_options_.is_incognito()) { | 326 if (file_system_options_.is_incognito()) { |
387 // TODO(kinuko): return an isolated temporary directory. | 327 // TODO(kinuko): return an isolated temporary directory. |
388 callback.Run(false, FilePath(), std::string()); | 328 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY); |
389 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, | 329 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, |
390 kIncognito, | 330 kIncognito, |
391 kFileSystemErrorMax); | 331 kFileSystemErrorMax); |
392 return; | 332 return; |
393 } | 333 } |
394 | 334 |
395 if (!IsAllowedScheme(origin_url)) { | 335 if (!IsAllowedScheme(origin_url)) { |
396 callback.Run(false, FilePath(), std::string()); | 336 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY); |
397 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, | 337 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, |
398 kInvalidScheme, | 338 kInvalidScheme, |
399 kFileSystemErrorMax); | 339 kFileSystemErrorMax); |
400 return; | 340 return; |
401 } | 341 } |
402 | 342 |
403 scoped_refptr<GetFileSystemRootPathTask> task( | 343 base::PlatformFileError* error_ptr = new base::PlatformFileError; |
404 new GetFileSystemRootPathTask( | 344 file_message_loop_->PostTaskAndReply( |
405 file_message_loop_, origin_url, type, sandbox_file_util_.get(), | 345 FROM_HERE, |
406 old_base_path(), callback)); | 346 base::Bind(&ValidateRootOnFileThread, |
407 task->Start(create); | 347 sandbox_file_util_, |
| 348 origin_url, type, old_base_path(), create, |
| 349 base::Unretained(error_ptr)), |
| 350 base::Bind(base::Bind(&PassPointerErrorByValue, callback), |
| 351 base::Owned(error_ptr))); |
408 }; | 352 }; |
409 | 353 |
410 FilePath | 354 FilePath |
411 SandboxMountPointProvider::ValidateFileSystemRootAndGetPathOnFileThread( | 355 SandboxMountPointProvider::GetFileSystemRootPathOnFileThread( |
412 const GURL& origin_url, FileSystemType type, const FilePath& unused, | 356 const GURL& origin_url, FileSystemType type, const FilePath& unused, |
413 bool create) { | 357 bool create) { |
414 if (file_system_options_.is_incognito()) | 358 if (file_system_options_.is_incognito()) |
415 // TODO(kinuko): return an isolated temporary directory. | 359 // TODO(kinuko): return an isolated temporary directory. |
416 return FilePath(); | 360 return FilePath(); |
417 | 361 |
418 if (!IsAllowedScheme(origin_url)) | 362 if (!IsAllowedScheme(origin_url)) |
419 return FilePath(); | 363 return FilePath(); |
420 | 364 |
421 MigrateIfNeeded(sandbox_file_util_, old_base_path()); | 365 MigrateIfNeeded(sandbox_file_util_, old_base_path()); |
422 | 366 |
423 return sandbox_file_util_->GetDirectoryForOriginAndType( | 367 return sandbox_file_util_->GetDirectoryForOriginAndType( |
424 origin_url, type, create); | 368 origin_url, type, create); |
425 } | 369 } |
426 | 370 |
| 371 bool SandboxMountPointProvider::IsAccessAllowed(const GURL& origin_url, |
| 372 FileSystemType type, |
| 373 const FilePath& unused) { |
| 374 if (type != kFileSystemTypeTemporary && type != kFileSystemTypePersistent) |
| 375 return false; |
| 376 // We essentially depend on quota to do our access controls, so here |
| 377 // we only check if the requested scheme is allowed or not. |
| 378 return IsAllowedScheme(origin_url); |
| 379 } |
| 380 |
427 bool SandboxMountPointProvider::IsRestrictedFileName(const FilePath& filename) | 381 bool SandboxMountPointProvider::IsRestrictedFileName(const FilePath& filename) |
428 const { | 382 const { |
429 if (filename.value().empty()) | 383 if (filename.value().empty()) |
430 return false; | 384 return false; |
431 | 385 |
432 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) { | 386 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) { |
433 // Exact match. | 387 // Exact match. |
434 if (filename.value() == kRestrictedNames[i]) | 388 if (filename.value() == kRestrictedNames[i]) |
435 return true; | 389 return true; |
436 } | 390 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 quota::QuotaClient::kFileSystem, | 451 quota::QuotaClient::kFileSystem, |
498 origin_url, | 452 origin_url, |
499 FileSystemTypeToQuotaStorageType(type), | 453 FileSystemTypeToQuotaStorageType(type), |
500 -usage); | 454 -usage); |
501 } | 455 } |
502 return result; | 456 return result; |
503 } | 457 } |
504 | 458 |
505 void SandboxMountPointProvider::GetOriginsForTypeOnFileThread( | 459 void SandboxMountPointProvider::GetOriginsForTypeOnFileThread( |
506 fileapi::FileSystemType type, std::set<GURL>* origins) { | 460 fileapi::FileSystemType type, std::set<GURL>* origins) { |
507 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 461 DCHECK(type == kFileSystemTypeTemporary || |
508 type == fileapi::kFileSystemTypePersistent); | 462 type == kFileSystemTypePersistent); |
509 DCHECK(origins); | 463 DCHECK(origins); |
510 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | 464 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); |
511 GURL origin; | 465 GURL origin; |
512 while (!(origin = enumerator->Next()).is_empty()) { | 466 while (!(origin = enumerator->Next()).is_empty()) { |
513 if (enumerator->HasFileSystemType(type)) | 467 if (enumerator->HasFileSystemType(type)) |
514 origins->insert(origin); | 468 origins->insert(origin); |
515 } | 469 } |
516 } | 470 } |
517 | 471 |
518 void SandboxMountPointProvider::GetOriginsForHostOnFileThread( | 472 void SandboxMountPointProvider::GetOriginsForHostOnFileThread( |
519 fileapi::FileSystemType type, const std::string& host, | 473 fileapi::FileSystemType type, const std::string& host, |
520 std::set<GURL>* origins) { | 474 std::set<GURL>* origins) { |
521 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 475 DCHECK(type == kFileSystemTypeTemporary || |
522 type == fileapi::kFileSystemTypePersistent); | 476 type == kFileSystemTypePersistent); |
523 DCHECK(origins); | 477 DCHECK(origins); |
524 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | 478 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); |
525 GURL origin; | 479 GURL origin; |
526 while (!(origin = enumerator->Next()).is_empty()) { | 480 while (!(origin = enumerator->Next()).is_empty()) { |
527 if (host == net::GetHostOrSpecFromURL(origin) && | 481 if (host == net::GetHostOrSpecFromURL(origin) && |
528 enumerator->HasFileSystemType(type)) | 482 enumerator->HasFileSystemType(type)) |
529 origins->insert(origin); | 483 origins->insert(origin); |
530 } | 484 } |
531 } | 485 } |
532 | 486 |
533 int64 SandboxMountPointProvider::GetOriginUsageOnFileThread( | 487 int64 SandboxMountPointProvider::GetOriginUsageOnFileThread( |
534 const GURL& origin_url, fileapi::FileSystemType type) { | 488 const GURL& origin_url, fileapi::FileSystemType type) { |
535 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 489 DCHECK(type == kFileSystemTypeTemporary || |
536 type == fileapi::kFileSystemTypePersistent); | 490 type == kFileSystemTypePersistent); |
537 FilePath base_path = | 491 FilePath base_path = |
538 GetBaseDirectoryForOriginAndType(origin_url, type, false); | 492 GetBaseDirectoryForOriginAndType(origin_url, type, false); |
539 if (base_path.empty() || !file_util::DirectoryExists(base_path)) return 0; | 493 if (base_path.empty() || !file_util::DirectoryExists(base_path)) return 0; |
540 FilePath usage_file_path = | 494 FilePath usage_file_path = |
541 base_path.AppendASCII(FileSystemUsageCache::kUsageFileName); | 495 base_path.AppendASCII(FileSystemUsageCache::kUsageFileName); |
542 | 496 |
543 bool is_valid = FileSystemUsageCache::IsValid(usage_file_path); | 497 bool is_valid = FileSystemUsageCache::IsValid(usage_file_path); |
544 int32 dirty_status = FileSystemUsageCache::GetDirty(usage_file_path); | 498 int32 dirty_status = FileSystemUsageCache::GetDirty(usage_file_path); |
545 bool visited = (visited_origins_.find(origin_url) != visited_origins_.end()); | 499 bool visited = (visited_origins_.find(origin_url) != visited_origins_.end()); |
546 visited_origins_.insert(origin_url); | 500 visited_origins_.insert(origin_url); |
(...skipping 22 matching lines...) Expand all Loading... |
569 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each); | 523 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each); |
570 } | 524 } |
571 // This clears the dirty flag too. | 525 // This clears the dirty flag too. |
572 FileSystemUsageCache::UpdateUsage(usage_file_path, usage); | 526 FileSystemUsageCache::UpdateUsage(usage_file_path, usage); |
573 return usage; | 527 return usage; |
574 } | 528 } |
575 | 529 |
576 void SandboxMountPointProvider::NotifyOriginWasAccessedOnIOThread( | 530 void SandboxMountPointProvider::NotifyOriginWasAccessedOnIOThread( |
577 QuotaManagerProxy* proxy, const GURL& origin_url, | 531 QuotaManagerProxy* proxy, const GURL& origin_url, |
578 fileapi::FileSystemType type) { | 532 fileapi::FileSystemType type) { |
579 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 533 DCHECK(type == kFileSystemTypeTemporary || |
580 type == fileapi::kFileSystemTypePersistent); | 534 type == kFileSystemTypePersistent); |
581 if (proxy) { | 535 if (proxy) { |
582 proxy->NotifyStorageAccessed( | 536 proxy->NotifyStorageAccessed( |
583 quota::QuotaClient::kFileSystem, | 537 quota::QuotaClient::kFileSystem, |
584 origin_url, | 538 origin_url, |
585 FileSystemTypeToQuotaStorageType(type)); | 539 FileSystemTypeToQuotaStorageType(type)); |
586 } | 540 } |
587 } | 541 } |
588 | 542 |
589 void SandboxMountPointProvider::UpdateOriginUsageOnFileThread( | 543 void SandboxMountPointProvider::UpdateOriginUsageOnFileThread( |
590 QuotaManagerProxy* proxy, const GURL& origin_url, | 544 QuotaManagerProxy* proxy, const GURL& origin_url, |
591 fileapi::FileSystemType type, int64 delta) { | 545 fileapi::FileSystemType type, int64 delta) { |
592 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 546 DCHECK(type == kFileSystemTypeTemporary || |
593 type == fileapi::kFileSystemTypePersistent); | 547 type == kFileSystemTypePersistent); |
594 FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 548 FilePath usage_file_path = GetUsageCachePathForOriginAndType( |
595 origin_url, type); | 549 origin_url, type); |
596 DCHECK(!usage_file_path.empty()); | 550 DCHECK(!usage_file_path.empty()); |
597 // TODO(dmikurbe): Make sure that usage_file_path is available. | 551 // TODO(dmikurbe): Make sure that usage_file_path is available. |
598 FileSystemUsageCache::AtomicUpdateUsageByDelta(usage_file_path, delta); | 552 FileSystemUsageCache::AtomicUpdateUsageByDelta(usage_file_path, delta); |
599 if (proxy) { | 553 if (proxy) { |
600 proxy->NotifyStorageModified( | 554 proxy->NotifyStorageModified( |
601 quota::QuotaClient::kFileSystem, | 555 quota::QuotaClient::kFileSystem, |
602 origin_url, | 556 origin_url, |
603 FileSystemTypeToQuotaStorageType(type), | 557 FileSystemTypeToQuotaStorageType(type), |
604 delta); | 558 delta); |
605 } | 559 } |
606 } | 560 } |
607 | 561 |
608 void SandboxMountPointProvider::StartUpdateOriginOnFileThread( | 562 void SandboxMountPointProvider::StartUpdateOriginOnFileThread( |
609 const GURL& origin_url, fileapi::FileSystemType type) { | 563 const GURL& origin_url, fileapi::FileSystemType type) { |
610 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 564 DCHECK(type == kFileSystemTypeTemporary || |
611 type == fileapi::kFileSystemTypePersistent); | 565 type == kFileSystemTypePersistent); |
612 FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 566 FilePath usage_file_path = GetUsageCachePathForOriginAndType( |
613 origin_url, type); | 567 origin_url, type); |
614 FileSystemUsageCache::IncrementDirty(usage_file_path); | 568 FileSystemUsageCache::IncrementDirty(usage_file_path); |
615 } | 569 } |
616 | 570 |
617 void SandboxMountPointProvider::EndUpdateOriginOnFileThread( | 571 void SandboxMountPointProvider::EndUpdateOriginOnFileThread( |
618 const GURL& origin_url, fileapi::FileSystemType type) { | 572 const GURL& origin_url, fileapi::FileSystemType type) { |
619 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 573 DCHECK(type == kFileSystemTypeTemporary || |
620 type == fileapi::kFileSystemTypePersistent); | 574 type == kFileSystemTypePersistent); |
621 FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 575 FilePath usage_file_path = GetUsageCachePathForOriginAndType( |
622 origin_url, type); | 576 origin_url, type); |
623 FileSystemUsageCache::DecrementDirty(usage_file_path); | 577 FileSystemUsageCache::DecrementDirty(usage_file_path); |
624 } | 578 } |
625 | 579 |
626 void SandboxMountPointProvider::InvalidateUsageCache( | 580 void SandboxMountPointProvider::InvalidateUsageCache( |
627 const GURL& origin_url, fileapi::FileSystemType type) { | 581 const GURL& origin_url, fileapi::FileSystemType type) { |
628 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 582 DCHECK(type == kFileSystemTypeTemporary || |
629 type == fileapi::kFileSystemTypePersistent); | 583 type == kFileSystemTypePersistent); |
630 FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 584 FilePath usage_file_path = GetUsageCachePathForOriginAndType( |
631 origin_url, type); | 585 origin_url, type); |
632 FileSystemUsageCache::IncrementDirty(usage_file_path); | 586 FileSystemUsageCache::IncrementDirty(usage_file_path); |
633 } | 587 } |
634 | 588 |
635 FilePath SandboxMountPointProvider::GetUsageCachePathForOriginAndType( | 589 FilePath SandboxMountPointProvider::GetUsageCachePathForOriginAndType( |
636 const GURL& origin_url, fileapi::FileSystemType type) const { | 590 const GURL& origin_url, fileapi::FileSystemType type) const { |
637 FilePath base_path = | 591 FilePath base_path = |
638 GetBaseDirectoryForOriginAndType(origin_url, type, false); | 592 GetBaseDirectoryForOriginAndType(origin_url, type, false); |
639 if (base_path.empty()) | 593 if (base_path.empty()) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 i < file_system_options_.additional_allowed_schemes().size(); | 629 i < file_system_options_.additional_allowed_schemes().size(); |
676 ++i) { | 630 ++i) { |
677 if (url.SchemeIs( | 631 if (url.SchemeIs( |
678 file_system_options_.additional_allowed_schemes()[i].c_str())) | 632 file_system_options_.additional_allowed_schemes()[i].c_str())) |
679 return true; | 633 return true; |
680 } | 634 } |
681 return false; | 635 return false; |
682 } | 636 } |
683 | 637 |
684 } // namespace fileapi | 638 } // namespace fileapi |
OLD | NEW |