Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Side by Side Diff: webkit/browser/fileapi/sandbox_mount_point_provider.cc

Issue 18344013: fileapi: Rename FileSystemMountProvider to FileSystemBackend (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "webkit/browser/fileapi/sandbox_mount_point_provider.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/file_util.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/histogram.h"
13 #include "base/stl_util.h"
14 #include "base/task_runner_util.h"
15 #include "net/base/net_util.h"
16 #include "url/gurl.h"
17 #include "webkit/browser/fileapi/async_file_util_adapter.h"
18 #include "webkit/browser/fileapi/copy_or_move_file_validator.h"
19 #include "webkit/browser/fileapi/file_system_context.h"
20 #include "webkit/browser/fileapi/file_system_file_stream_reader.h"
21 #include "webkit/browser/fileapi/file_system_operation_context.h"
22 #include "webkit/browser/fileapi/file_system_options.h"
23 #include "webkit/browser/fileapi/file_system_task_runners.h"
24 #include "webkit/browser/fileapi/file_system_usage_cache.h"
25 #include "webkit/browser/fileapi/local_file_system_operation.h"
26 #include "webkit/browser/fileapi/obfuscated_file_util.h"
27 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h"
28 #include "webkit/browser/fileapi/sandbox_quota_observer.h"
29 #include "webkit/browser/fileapi/syncable/syncable_file_system_operation.h"
30 #include "webkit/browser/quota/quota_manager.h"
31 #include "webkit/common/fileapi/file_system_types.h"
32 #include "webkit/common/fileapi/file_system_util.h"
33
34 using quota::QuotaManagerProxy;
35
36 namespace fileapi {
37
38 namespace {
39
40 const char kChromeScheme[] = "chrome";
41 const char kExtensionScheme[] = "chrome-extension";
42
43 const char kOpenFileSystemLabel[] = "FileSystem.OpenFileSystem";
44 const char kOpenFileSystemDetailLabel[] = "FileSystem.OpenFileSystemDetail";
45 const char kOpenFileSystemDetailNonThrottledLabel[] =
46 "FileSystem.OpenFileSystemDetailNonthrottled";
47 int64 kMinimumStatsCollectionIntervalHours = 1;
48
49 // A command line switch to disable usage tracking.
50 const char kDisableUsageTracking[] = "disable-file-system-usage-tracking";
51
52 enum FileSystemError {
53 kOK = 0,
54 kIncognito,
55 kInvalidSchemeError,
56 kCreateDirectoryError,
57 kNotFound,
58 kUnknownError,
59 kFileSystemErrorMax,
60 };
61
62 const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount";
63 const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount";
64 const char kSyncableOriginsCountLabel[] = "FileSystem.SyncableOriginsCount";
65
66 // Restricted names.
67 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
68 const base::FilePath::CharType* const kRestrictedNames[] = {
69 FILE_PATH_LITERAL("."), FILE_PATH_LITERAL(".."),
70 };
71
72 // Restricted chars.
73 const base::FilePath::CharType kRestrictedChars[] = {
74 FILE_PATH_LITERAL('/'), FILE_PATH_LITERAL('\\'),
75 };
76
77 class ObfuscatedOriginEnumerator
78 : public SandboxMountPointProvider::OriginEnumerator {
79 public:
80 explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) {
81 enum_.reset(file_util->CreateOriginEnumerator());
82 }
83 virtual ~ObfuscatedOriginEnumerator() {}
84
85 virtual GURL Next() OVERRIDE {
86 return enum_->Next();
87 }
88
89 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE {
90 return enum_->HasFileSystemType(type);
91 }
92
93 private:
94 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_;
95 };
96
97 void DidOpenFileSystem(
98 base::WeakPtr<SandboxMountPointProvider> mount_point_provider,
99 const FileSystemMountPointProvider::OpenFileSystemCallback& callback,
100 base::PlatformFileError* error) {
101 if (mount_point_provider.get())
102 mount_point_provider.get()->CollectOpenFileSystemMetrics(*error);
103 callback.Run(*error);
104 }
105
106 void OpenFileSystemOnFileThread(
107 ObfuscatedFileUtil* file_util,
108 const GURL& origin_url,
109 FileSystemType type,
110 OpenFileSystemMode mode,
111 base::PlatformFileError* error_ptr) {
112 DCHECK(error_ptr);
113
114 const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT);
115 base::FilePath root_path =
116 file_util->GetDirectoryForOriginAndType(
117 origin_url, type, create, error_ptr);
118 if (*error_ptr != base::PLATFORM_FILE_OK) {
119 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel,
120 kCreateDirectoryError,
121 kFileSystemErrorMax);
122 } else {
123 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kOK, kFileSystemErrorMax);
124 }
125 // The reference of file_util will be derefed on the FILE thread
126 // when the storage of this callback gets deleted regardless of whether
127 // this method is called or not.
128 }
129
130 } // anonymous namespace
131
132 const base::FilePath::CharType
133 SandboxMountPointProvider::kFileSystemDirectory[] =
134 FILE_PATH_LITERAL("File System");
135
136 SandboxMountPointProvider::SandboxMountPointProvider(
137 quota::QuotaManagerProxy* quota_manager_proxy,
138 base::SequencedTaskRunner* file_task_runner,
139 const base::FilePath& profile_path,
140 const FileSystemOptions& file_system_options,
141 quota::SpecialStoragePolicy* special_storage_policy)
142 : file_task_runner_(file_task_runner),
143 profile_path_(profile_path),
144 file_system_options_(file_system_options),
145 enable_temporary_file_system_in_incognito_(false),
146 sandbox_file_util_(
147 new AsyncFileUtilAdapter(
148 new ObfuscatedFileUtil(
149 special_storage_policy,
150 profile_path.Append(kFileSystemDirectory),
151 file_task_runner))),
152 file_system_usage_cache_(new FileSystemUsageCache(file_task_runner)),
153 quota_observer_(new SandboxQuotaObserver(
154 quota_manager_proxy,
155 file_task_runner,
156 sandbox_sync_file_util(),
157 file_system_usage_cache_.get())),
158 enable_usage_tracking_(
159 !CommandLine::ForCurrentProcess()->HasSwitch(
160 kDisableUsageTracking)),
161 special_storage_policy_(special_storage_policy),
162 weak_factory_(this) {
163 // Set quota observers.
164 UpdateObserverList::Source update_observers_src;
165 AccessObserverList::Source access_observers_src;
166
167 if (enable_usage_tracking_) {
168 update_observers_src.AddObserver(quota_observer_.get(),
169 file_task_runner_.get());
170 access_observers_src.AddObserver(quota_observer_.get(), NULL);
171 }
172
173 update_observers_ = UpdateObserverList(update_observers_src);
174 access_observers_ = AccessObserverList(access_observers_src);
175 syncable_update_observers_ = UpdateObserverList(update_observers_src);
176
177 if (!file_task_runner_->RunsTasksOnCurrentThread()) {
178 // Post prepopulate task only if it's not already running on
179 // file_task_runner (which implies running in tests).
180 file_task_runner_->PostTask(
181 FROM_HERE,
182 base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase,
183 base::Unretained(sandbox_sync_file_util())));
184 }
185 }
186
187 SandboxMountPointProvider::~SandboxMountPointProvider() {
188 if (!file_task_runner_->RunsTasksOnCurrentThread()) {
189 AsyncFileUtilAdapter* sandbox_file_util = sandbox_file_util_.release();
190 SandboxQuotaObserver* quota_observer = quota_observer_.release();
191 FileSystemUsageCache* file_system_usage_cache =
192 file_system_usage_cache_.release();
193 if (!file_task_runner_->DeleteSoon(FROM_HERE, sandbox_file_util))
194 delete sandbox_file_util;
195 if (!file_task_runner_->DeleteSoon(FROM_HERE, quota_observer))
196 delete quota_observer;
197 if (!file_task_runner_->DeleteSoon(FROM_HERE, file_system_usage_cache))
198 delete file_system_usage_cache;
199 }
200 }
201
202 bool SandboxMountPointProvider::CanHandleType(FileSystemType type) const {
203 return type == kFileSystemTypeTemporary ||
204 type == kFileSystemTypePersistent ||
205 type == kFileSystemTypeSyncable ||
206 type == kFileSystemTypeSyncableForInternalSync;
207 }
208
209 void SandboxMountPointProvider::OpenFileSystem(
210 const GURL& origin_url, fileapi::FileSystemType type,
211 OpenFileSystemMode mode,
212 const OpenFileSystemCallback& callback) {
213 if (file_system_options_.is_incognito() &&
214 !(type == kFileSystemTypeTemporary &&
215 enable_temporary_file_system_in_incognito_)) {
216 // TODO(kinuko): return an isolated temporary directory.
217 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
218 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel,
219 kIncognito,
220 kFileSystemErrorMax);
221 return;
222 }
223
224 if (!IsAllowedScheme(origin_url)) {
225 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
226 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel,
227 kInvalidSchemeError,
228 kFileSystemErrorMax);
229 return;
230 }
231
232 base::PlatformFileError* error_ptr = new base::PlatformFileError;
233 file_task_runner_->PostTaskAndReply(
234 FROM_HERE,
235 base::Bind(&OpenFileSystemOnFileThread,
236 sandbox_sync_file_util(),
237 origin_url, type, mode,
238 base::Unretained(error_ptr)),
239 base::Bind(&DidOpenFileSystem,
240 weak_factory_.GetWeakPtr(),
241 callback, base::Owned(error_ptr)));
242
243 if (enable_usage_tracking_)
244 return;
245
246 // Schedule full usage recalculation on the next launch without
247 // --disable-file-system-usage-tracking.
248 file_task_runner_->PostTask(
249 FROM_HERE,
250 base::Bind(&SandboxMountPointProvider::InvalidateUsageCacheOnFileThread,
251 sandbox_sync_file_util(), origin_url, type,
252 file_system_usage_cache_.get()));
253 };
254
255 FileSystemFileUtil* SandboxMountPointProvider::GetFileUtil(
256 FileSystemType type) {
257 DCHECK(sandbox_file_util_.get());
258 return sandbox_file_util_->sync_file_util();
259 }
260
261 AsyncFileUtil* SandboxMountPointProvider::GetAsyncFileUtil(
262 FileSystemType type) {
263 return sandbox_file_util_.get();
264 }
265
266 CopyOrMoveFileValidatorFactory*
267 SandboxMountPointProvider::GetCopyOrMoveFileValidatorFactory(
268 FileSystemType type,
269 base::PlatformFileError* error_code) {
270 DCHECK(error_code);
271 *error_code = base::PLATFORM_FILE_OK;
272 return NULL;
273 }
274
275 FileSystemOperation* SandboxMountPointProvider::CreateFileSystemOperation(
276 const FileSystemURL& url,
277 FileSystemContext* context,
278 base::PlatformFileError* error_code) const {
279 if (!IsAccessValid(url)) {
280 *error_code = base::PLATFORM_FILE_ERROR_SECURITY;
281 return NULL;
282 }
283
284 scoped_ptr<FileSystemOperationContext> operation_context(
285 new FileSystemOperationContext(context));
286
287 // Copy the observer lists (assuming we only have small number of observers).
288 if (url.type() == kFileSystemTypeSyncable) {
289 operation_context->set_update_observers(syncable_update_observers_);
290 operation_context->set_change_observers(syncable_change_observers_);
291 return new sync_file_system::SyncableFileSystemOperation(
292 url, context, operation_context.Pass());
293 }
294
295 // For regular sandboxed types.
296 operation_context->set_update_observers(update_observers_);
297 operation_context->set_change_observers(change_observers_);
298
299 if (special_storage_policy_.get() &&
300 special_storage_policy_->IsStorageUnlimited(url.origin())) {
301 operation_context->set_quota_limit_type(quota::kQuotaLimitTypeUnlimited);
302 } else {
303 operation_context->set_quota_limit_type(quota::kQuotaLimitTypeLimited);
304 }
305
306 return new LocalFileSystemOperation(url, context, operation_context.Pass());
307 }
308
309 scoped_ptr<webkit_blob::FileStreamReader>
310 SandboxMountPointProvider::CreateFileStreamReader(
311 const FileSystemURL& url,
312 int64 offset,
313 const base::Time& expected_modification_time,
314 FileSystemContext* context) const {
315 if (!IsAccessValid(url))
316 return scoped_ptr<webkit_blob::FileStreamReader>();
317 return scoped_ptr<webkit_blob::FileStreamReader>(
318 new FileSystemFileStreamReader(
319 context, url, offset, expected_modification_time));
320 }
321
322 scoped_ptr<fileapi::FileStreamWriter>
323 SandboxMountPointProvider::CreateFileStreamWriter(
324 const FileSystemURL& url,
325 int64 offset,
326 FileSystemContext* context) const {
327 if (!IsAccessValid(url))
328 return scoped_ptr<fileapi::FileStreamWriter>();
329 return scoped_ptr<fileapi::FileStreamWriter>(
330 new SandboxFileStreamWriter(context, url, offset, update_observers_));
331 }
332
333 FileSystemQuotaUtil* SandboxMountPointProvider::GetQuotaUtil() {
334 return this;
335 }
336
337 void SandboxMountPointProvider::DeleteFileSystem(
338 const GURL& origin_url,
339 FileSystemType type,
340 FileSystemContext* context,
341 const DeleteFileSystemCallback& callback) {
342 base::PostTaskAndReplyWithResult(
343 context->task_runners()->file_task_runner(),
344 FROM_HERE,
345 // It is safe to pass Unretained(this) since context owns it.
346 base::Bind(&SandboxMountPointProvider::DeleteOriginDataOnFileThread,
347 base::Unretained(this),
348 make_scoped_refptr(context),
349 base::Unretained(context->quota_manager_proxy()),
350 origin_url,
351 type),
352 callback);
353 }
354
355 SandboxMountPointProvider::OriginEnumerator*
356 SandboxMountPointProvider::CreateOriginEnumerator() {
357 return new ObfuscatedOriginEnumerator(sandbox_sync_file_util());
358 }
359
360 base::FilePath SandboxMountPointProvider::GetBaseDirectoryForOriginAndType(
361 const GURL& origin_url, fileapi::FileSystemType type, bool create) {
362
363 base::PlatformFileError error = base::PLATFORM_FILE_OK;
364 base::FilePath path = sandbox_sync_file_util()->GetDirectoryForOriginAndType(
365 origin_url, type, create, &error);
366 if (error != base::PLATFORM_FILE_OK)
367 return base::FilePath();
368 return path;
369 }
370
371 base::PlatformFileError
372 SandboxMountPointProvider::DeleteOriginDataOnFileThread(
373 FileSystemContext* file_system_context,
374 QuotaManagerProxy* proxy,
375 const GURL& origin_url,
376 fileapi::FileSystemType type) {
377
378 int64 usage = GetOriginUsageOnFileThread(file_system_context,
379 origin_url, type);
380
381 file_system_usage_cache_->CloseCacheFiles();
382 bool result = sandbox_sync_file_util()->DeleteDirectoryForOriginAndType(
383 origin_url, type);
384 if (result && proxy) {
385 proxy->NotifyStorageModified(
386 quota::QuotaClient::kFileSystem,
387 origin_url,
388 FileSystemTypeToQuotaStorageType(type),
389 -usage);
390 }
391
392 if (result)
393 return base::PLATFORM_FILE_OK;
394 return base::PLATFORM_FILE_ERROR_FAILED;
395 }
396
397 void SandboxMountPointProvider::GetOriginsForTypeOnFileThread(
398 fileapi::FileSystemType type, std::set<GURL>* origins) {
399 DCHECK(CanHandleType(type));
400 DCHECK(origins);
401 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator());
402 GURL origin;
403 while (!(origin = enumerator->Next()).is_empty()) {
404 if (enumerator->HasFileSystemType(type))
405 origins->insert(origin);
406 }
407 switch (type) {
408 case kFileSystemTypeTemporary:
409 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size());
410 break;
411 case kFileSystemTypePersistent:
412 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size());
413 break;
414 case kFileSystemTypeSyncable:
415 UMA_HISTOGRAM_COUNTS(kSyncableOriginsCountLabel, origins->size());
416 break;
417 default:
418 break;
419 }
420 }
421
422 void SandboxMountPointProvider::GetOriginsForHostOnFileThread(
423 fileapi::FileSystemType type, const std::string& host,
424 std::set<GURL>* origins) {
425 DCHECK(CanHandleType(type));
426 DCHECK(origins);
427 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator());
428 GURL origin;
429 while (!(origin = enumerator->Next()).is_empty()) {
430 if (host == net::GetHostOrSpecFromURL(origin) &&
431 enumerator->HasFileSystemType(type))
432 origins->insert(origin);
433 }
434 }
435
436 int64 SandboxMountPointProvider::GetOriginUsageOnFileThread(
437 FileSystemContext* file_system_context,
438 const GURL& origin_url,
439 fileapi::FileSystemType type) {
440 DCHECK(CanHandleType(type));
441 if (!enable_usage_tracking_)
442 return 0;
443
444 // Don't use usage cache and return recalculated usage for sticky invalidated
445 // origins.
446 if (ContainsKey(sticky_dirty_origins_, std::make_pair(origin_url, type)))
447 return RecalculateUsage(file_system_context, origin_url, type);
448
449 base::FilePath base_path =
450 GetBaseDirectoryForOriginAndType(origin_url, type, false);
451 if (base_path.empty() || !file_util::DirectoryExists(base_path))
452 return 0;
453 base::FilePath usage_file_path =
454 base_path.Append(FileSystemUsageCache::kUsageFileName);
455
456 bool is_valid = file_system_usage_cache_->IsValid(usage_file_path);
457 uint32 dirty_status = 0;
458 bool dirty_status_available =
459 file_system_usage_cache_->GetDirty(usage_file_path, &dirty_status);
460 bool visited = !visited_origins_.insert(origin_url).second;
461 if (is_valid && (dirty_status == 0 || (dirty_status_available && visited))) {
462 // The usage cache is clean (dirty == 0) or the origin is already
463 // initialized and running. Read the cache file to get the usage.
464 int64 usage = 0;
465 return file_system_usage_cache_->GetUsage(usage_file_path, &usage) ?
466 usage : -1;
467 }
468 // The usage cache has not been initialized or the cache is dirty.
469 // Get the directory size now and update the cache.
470 file_system_usage_cache_->Delete(usage_file_path);
471
472 int64 usage = RecalculateUsage(file_system_context, origin_url, type);
473
474 // This clears the dirty flag too.
475 file_system_usage_cache_->UpdateUsage(usage_file_path, usage);
476 return usage;
477 }
478
479 void SandboxMountPointProvider::InvalidateUsageCache(
480 const GURL& origin,
481 fileapi::FileSystemType type) {
482 DCHECK(CanHandleType(type));
483 base::PlatformFileError error = base::PLATFORM_FILE_OK;
484 base::FilePath usage_file_path = GetUsageCachePathForOriginAndType(
485 sandbox_sync_file_util(), origin, type, &error);
486 if (error != base::PLATFORM_FILE_OK)
487 return;
488 file_system_usage_cache_->IncrementDirty(usage_file_path);
489 }
490
491 void SandboxMountPointProvider::StickyInvalidateUsageCache(
492 const GURL& origin,
493 fileapi::FileSystemType type) {
494 DCHECK(CanHandleType(type));
495 sticky_dirty_origins_.insert(std::make_pair(origin, type));
496 quota_observer_->SetUsageCacheEnabled(origin, type, false);
497 InvalidateUsageCache(origin, type);
498 }
499
500 void SandboxMountPointProvider::CollectOpenFileSystemMetrics(
501 base::PlatformFileError error_code) {
502 base::Time now = base::Time::Now();
503 bool throttled = now < next_release_time_for_open_filesystem_stat_;
504 if (!throttled) {
505 next_release_time_for_open_filesystem_stat_ =
506 now + base::TimeDelta::FromHours(kMinimumStatsCollectionIntervalHours);
507 }
508
509 #define REPORT(report_value) \
510 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailLabel, \
511 (report_value), \
512 kFileSystemErrorMax); \
513 if (!throttled) { \
514 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailNonThrottledLabel, \
515 (report_value), \
516 kFileSystemErrorMax); \
517 }
518
519 switch (error_code) {
520 case base::PLATFORM_FILE_OK:
521 REPORT(kOK);
522 break;
523 case base::PLATFORM_FILE_ERROR_INVALID_URL:
524 REPORT(kInvalidSchemeError);
525 break;
526 case base::PLATFORM_FILE_ERROR_NOT_FOUND:
527 REPORT(kNotFound);
528 break;
529 case base::PLATFORM_FILE_ERROR_FAILED:
530 default:
531 REPORT(kUnknownError);
532 break;
533 }
534 #undef REPORT
535 }
536
537 const UpdateObserverList* SandboxMountPointProvider::GetUpdateObservers(
538 FileSystemType type) const {
539 DCHECK(CanHandleType(type));
540 if (type == kFileSystemTypeSyncable)
541 return &syncable_update_observers_;
542 return &update_observers_;
543 }
544
545 const AccessObserverList* SandboxMountPointProvider::GetAccessObservers(
546 FileSystemType type) const {
547 DCHECK(CanHandleType(type));
548 return &access_observers_;
549 }
550
551 void SandboxMountPointProvider::AddFileUpdateObserver(
552 FileSystemType type,
553 FileUpdateObserver* observer,
554 base::SequencedTaskRunner* task_runner) {
555 DCHECK(CanHandleType(type));
556 UpdateObserverList* list = &update_observers_;
557 if (type == kFileSystemTypeSyncable)
558 list = &syncable_update_observers_;
559 UpdateObserverList::Source observer_source = list->source();
560 observer_source.AddObserver(observer, task_runner);
561 *list = UpdateObserverList(observer_source);
562 }
563
564 void SandboxMountPointProvider::AddFileChangeObserver(
565 FileSystemType type,
566 FileChangeObserver* observer,
567 base::SequencedTaskRunner* task_runner) {
568 ChangeObserverList* list = &change_observers_;
569 if (type == kFileSystemTypeSyncable)
570 list = &syncable_change_observers_;
571 ChangeObserverList::Source observer_source = list->source();
572 observer_source.AddObserver(observer, task_runner);
573 *list = ChangeObserverList(observer_source);
574 }
575
576 bool SandboxMountPointProvider::IsAccessValid(
577 const FileSystemURL& url) const {
578 if (!IsAllowedScheme(url.origin()))
579 return false;
580
581 if (!CanHandleType(url.type()))
582 return false;
583
584 if (url.path().ReferencesParent())
585 return false;
586
587 // Return earlier if the path is '/', because VirtualPath::BaseName()
588 // returns '/' for '/' and we fail the "basename != '/'" check below.
589 // (We exclude '.' because it's disallowed by spec.)
590 if (VirtualPath::IsRootPath(url.path()) &&
591 url.path() != base::FilePath(base::FilePath::kCurrentDirectory))
592 return true;
593
594 // Restricted names specified in
595 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restriction s
596 base::FilePath filename = VirtualPath::BaseName(url.path());
597 // See if the name is allowed to create.
598 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
599 if (filename.value() == kRestrictedNames[i])
600 return false;
601 }
602 for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
603 if (filename.value().find(kRestrictedChars[i]) !=
604 base::FilePath::StringType::npos)
605 return false;
606 }
607
608 return true;
609 }
610
611 base::FilePath SandboxMountPointProvider::GetUsageCachePathForOriginAndType(
612 const GURL& origin_url,
613 FileSystemType type) {
614 base::PlatformFileError error;
615 base::FilePath path = GetUsageCachePathForOriginAndType(
616 sandbox_sync_file_util(), origin_url, type, &error);
617 if (error != base::PLATFORM_FILE_OK)
618 return base::FilePath();
619 return path;
620 }
621
622 // static
623 base::FilePath SandboxMountPointProvider::GetUsageCachePathForOriginAndType(
624 ObfuscatedFileUtil* sandbox_file_util,
625 const GURL& origin_url,
626 fileapi::FileSystemType type,
627 base::PlatformFileError* error_out) {
628 DCHECK(error_out);
629 *error_out = base::PLATFORM_FILE_OK;
630 base::FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType(
631 origin_url, type, false /* create */, error_out);
632 if (*error_out != base::PLATFORM_FILE_OK)
633 return base::FilePath();
634 return base_path.Append(FileSystemUsageCache::kUsageFileName);
635 }
636
637 bool SandboxMountPointProvider::IsAllowedScheme(const GURL& url) const {
638 // Basically we only accept http or https. We allow file:// URLs
639 // only if --allow-file-access-from-files flag is given.
640 if (url.SchemeIs("http") || url.SchemeIs("https"))
641 return true;
642 if (url.SchemeIsFileSystem())
643 return url.inner_url() && IsAllowedScheme(*url.inner_url());
644
645 for (size_t i = 0;
646 i < file_system_options_.additional_allowed_schemes().size();
647 ++i) {
648 if (url.SchemeIs(
649 file_system_options_.additional_allowed_schemes()[i].c_str()))
650 return true;
651 }
652 return false;
653 }
654
655 ObfuscatedFileUtil* SandboxMountPointProvider::sandbox_sync_file_util() {
656 DCHECK(sandbox_file_util_.get());
657 return static_cast<ObfuscatedFileUtil*>(sandbox_file_util_->sync_file_util());
658 }
659
660 // static
661 void SandboxMountPointProvider::InvalidateUsageCacheOnFileThread(
662 ObfuscatedFileUtil* file_util,
663 const GURL& origin,
664 FileSystemType type,
665 FileSystemUsageCache* usage_cache) {
666 base::PlatformFileError error = base::PLATFORM_FILE_OK;
667 base::FilePath usage_cache_path = GetUsageCachePathForOriginAndType(
668 file_util, origin, type, &error);
669 if (error == base::PLATFORM_FILE_OK)
670 usage_cache->IncrementDirty(usage_cache_path);
671 }
672
673 int64 SandboxMountPointProvider::RecalculateUsage(FileSystemContext* context,
674 const GURL& origin,
675 FileSystemType type) {
676 FileSystemOperationContext operation_context(context);
677 FileSystemURL url = context->CreateCrackedFileSystemURL(
678 origin, type, base::FilePath());
679 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator(
680 sandbox_sync_file_util()->CreateFileEnumerator(
681 &operation_context, url, true));
682
683 base::FilePath file_path_each;
684 int64 usage = 0;
685
686 while (!(file_path_each = enumerator->Next()).empty()) {
687 usage += enumerator->Size();
688 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each);
689 }
690
691 return usage;
692 }
693
694 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698