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

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

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

Powered by Google App Engine
This is Rietveld 408576698