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

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

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

Powered by Google App Engine
This is Rietveld 408576698