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.
5 #include "webkit/fileapi/sandbox_mount_point_provider.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/task_runner_util.h"
13 #include "googleurl/src/gurl.h"
14 #include "net/base/net_util.h"
15 #include "webkit/fileapi/async_file_util_adapter.h"
16 #include "webkit/fileapi/copy_or_move_file_validator.h"
17 #include "webkit/fileapi/file_system_context.h"
18 #include "webkit/fileapi/file_system_file_stream_reader.h"
19 #include "webkit/fileapi/file_system_operation_context.h"
20 #include "webkit/fileapi/file_system_options.h"
21 #include "webkit/fileapi/file_system_task_runners.h"
22 #include "webkit/fileapi/file_system_types.h"
23 #include "webkit/fileapi/file_system_usage_cache.h"
24 #include "webkit/fileapi/file_system_util.h"
25 #include "webkit/fileapi/local_file_system_operation.h"
26 #include "webkit/fileapi/obfuscated_file_util.h"
27 #include "webkit/fileapi/sandbox_file_stream_writer.h"
28 #include "webkit/fileapi/sandbox_quota_observer.h"
29 #include "webkit/fileapi/syncable/syncable_file_system_operation.h"
30 #include "webkit/quota/quota_manager.h"
32 using quota::QuotaManagerProxy
;
38 const char kChromeScheme
[] = "chrome";
39 const char kExtensionScheme
[] = "chrome-extension";
41 const char kOpenFileSystemLabel
[] = "FileSystem.OpenFileSystem";
42 const char kOpenFileSystemDetailLabel
[] = "FileSystem.OpenFileSystemDetail";
43 const char kOpenFileSystemDetailNonThrottledLabel
[] =
44 "FileSystem.OpenFileSystemDetailNonthrottled";
45 int64 kMinimumStatsCollectionIntervalHours
= 1;
47 // A command switch to enable syncing directory operations in Sync FileSystem
48 // API. (http://crbug.com/161442)
49 // TODO(kinuko): this command-line switch should be temporary.
50 const char kEnableSyncDirectoryOperation
[] = "enable-sync-directory-operation";
52 // A command line switch to disable usage tracking.
53 const char kDisableUsageTracking
[] = "disable-file-system-usage-tracking";
55 enum FileSystemError
{
59 kCreateDirectoryError
,
65 const char kTemporaryOriginsCountLabel
[] = "FileSystem.TemporaryOriginsCount";
66 const char kPersistentOriginsCountLabel
[] = "FileSystem.PersistentOriginsCount";
69 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
70 const base::FilePath::CharType
* const kRestrictedNames
[] = {
71 FILE_PATH_LITERAL("."), FILE_PATH_LITERAL(".."),
75 const base::FilePath::CharType kRestrictedChars
[] = {
76 FILE_PATH_LITERAL('/'), FILE_PATH_LITERAL('\\'),
79 class ObfuscatedOriginEnumerator
80 : public SandboxMountPointProvider::OriginEnumerator
{
82 explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil
* file_util
) {
83 enum_
.reset(file_util
->CreateOriginEnumerator());
85 virtual ~ObfuscatedOriginEnumerator() {}
87 virtual GURL
Next() OVERRIDE
{
91 virtual bool HasFileSystemType(fileapi::FileSystemType type
) const OVERRIDE
{
92 return enum_
->HasFileSystemType(type
);
96 scoped_ptr
<ObfuscatedFileUtil::AbstractOriginEnumerator
> enum_
;
99 void DidValidateFileSystemRoot(
100 base::WeakPtr
<SandboxMountPointProvider
> mount_point_provider
,
101 const FileSystemMountPointProvider::ValidateFileSystemCallback
& callback
,
102 base::PlatformFileError
* error
) {
103 if (mount_point_provider
.get())
104 mount_point_provider
.get()->CollectOpenFileSystemMetrics(*error
);
105 callback
.Run(*error
);
108 void ValidateRootOnFileThread(
109 ObfuscatedFileUtil
* file_util
,
110 const GURL
& origin_url
,
113 base::PlatformFileError
* error_ptr
) {
116 base::FilePath root_path
=
117 file_util
->GetDirectoryForOriginAndType(
118 origin_url
, type
, create
, error_ptr
);
119 if (*error_ptr
!= base::PLATFORM_FILE_OK
) {
120 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel
,
121 kCreateDirectoryError
,
122 kFileSystemErrorMax
);
124 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel
, kOK
, kFileSystemErrorMax
);
126 // The reference of file_util will be derefed on the FILE thread
127 // when the storage of this callback gets deleted regardless of whether
128 // this method is called or not.
131 } // anonymous namespace
133 const base::FilePath::CharType
134 SandboxMountPointProvider::kFileSystemDirectory
[] =
135 FILE_PATH_LITERAL("File System");
138 bool SandboxMountPointProvider::CanHandleType(FileSystemType type
) {
139 return type
== kFileSystemTypeTemporary
||
140 type
== kFileSystemTypePersistent
||
141 type
== kFileSystemTypeSyncable
;
144 SandboxMountPointProvider::SandboxMountPointProvider(
145 quota::QuotaManagerProxy
* quota_manager_proxy
,
146 base::SequencedTaskRunner
* file_task_runner
,
147 const base::FilePath
& profile_path
,
148 const FileSystemOptions
& file_system_options
)
149 : file_task_runner_(file_task_runner
),
150 profile_path_(profile_path
),
151 file_system_options_(file_system_options
),
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(
160 sandbox_sync_file_util(),
161 file_system_usage_cache_
.get())),
162 enable_sync_directory_operation_(
163 CommandLine::ForCurrentProcess()->HasSwitch(
164 kEnableSyncDirectoryOperation
)),
165 enable_usage_tracking_(
166 !CommandLine::ForCurrentProcess()->HasSwitch(
167 kDisableUsageTracking
)),
168 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
169 // Set quota observers.
170 UpdateObserverList::Source update_observers_src
;
171 AccessObserverList::Source access_observers_src
;
173 if (enable_usage_tracking_
) {
174 update_observers_src
.AddObserver(quota_observer_
.get(), file_task_runner_
);
175 access_observers_src
.AddObserver(quota_observer_
.get(), NULL
);
178 update_observers_
= UpdateObserverList(update_observers_src
);
179 access_observers_
= AccessObserverList(access_observers_src
);
180 syncable_update_observers_
= UpdateObserverList(update_observers_src
);
183 SandboxMountPointProvider::~SandboxMountPointProvider() {
184 if (!file_task_runner_
->RunsTasksOnCurrentThread()) {
185 AsyncFileUtilAdapter
* sandbox_file_util
= sandbox_file_util_
.release();
186 SandboxQuotaObserver
* quota_observer
= quota_observer_
.release();
187 FileSystemUsageCache
* file_system_usage_cache
=
188 file_system_usage_cache_
.release();
189 if (!file_task_runner_
->DeleteSoon(FROM_HERE
, sandbox_file_util
))
190 delete sandbox_file_util
;
191 if (!file_task_runner_
->DeleteSoon(FROM_HERE
, quota_observer
))
192 delete quota_observer
;
193 if (!file_task_runner_
->DeleteSoon(FROM_HERE
, file_system_usage_cache
))
194 delete file_system_usage_cache
;
198 void SandboxMountPointProvider::ValidateFileSystemRoot(
199 const GURL
& origin_url
, fileapi::FileSystemType type
, bool create
,
200 const ValidateFileSystemCallback
& callback
) {
201 if (file_system_options_
.is_incognito()) {
202 // TODO(kinuko): return an isolated temporary directory.
203 callback
.Run(base::PLATFORM_FILE_ERROR_SECURITY
);
204 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel
,
206 kFileSystemErrorMax
);
210 if (!IsAllowedScheme(origin_url
)) {
211 callback
.Run(base::PLATFORM_FILE_ERROR_SECURITY
);
212 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel
,
214 kFileSystemErrorMax
);
218 base::PlatformFileError
* error_ptr
= new base::PlatformFileError
;
219 file_task_runner_
->PostTaskAndReply(
221 base::Bind(&ValidateRootOnFileThread
,
222 sandbox_sync_file_util(),
223 origin_url
, type
, create
,
224 base::Unretained(error_ptr
)),
225 base::Bind(&DidValidateFileSystemRoot
,
226 weak_factory_
.GetWeakPtr(),
227 callback
, base::Owned(error_ptr
)));
229 if (enable_usage_tracking_
)
232 // Schedule full usage recalculation on the next launch without
233 // --disable-file-system-usage-tracking.
234 file_task_runner_
->PostTask(
236 base::Bind(&SandboxMountPointProvider::InvalidateUsageCacheOnFileThread
,
237 sandbox_sync_file_util(), origin_url
, type
,
238 file_system_usage_cache_
.get()));
242 SandboxMountPointProvider::GetFileSystemRootPathOnFileThread(
243 const FileSystemURL
& url
,
245 if (file_system_options_
.is_incognito())
246 // TODO(kinuko): return an isolated temporary directory.
247 return base::FilePath();
249 if (!IsAllowedScheme(url
.origin()))
250 return base::FilePath();
252 return GetBaseDirectoryForOriginAndType(url
.origin(), url
.type(), create
);
255 FileSystemFileUtil
* SandboxMountPointProvider::GetFileUtil(
256 FileSystemType type
) {
257 DCHECK(sandbox_file_util_
.get());
258 return sandbox_file_util_
->sync_file_util();
261 AsyncFileUtil
* SandboxMountPointProvider::GetAsyncFileUtil(
262 FileSystemType type
) {
263 return sandbox_file_util_
.get();
266 CopyOrMoveFileValidatorFactory
*
267 SandboxMountPointProvider::GetCopyOrMoveFileValidatorFactory(
269 base::PlatformFileError
* error_code
) {
271 *error_code
= base::PLATFORM_FILE_OK
;
275 void SandboxMountPointProvider::InitializeCopyOrMoveFileValidatorFactory(
277 scoped_ptr
<CopyOrMoveFileValidatorFactory
> factory
) {
281 FilePermissionPolicy
SandboxMountPointProvider::GetPermissionPolicy(
282 const FileSystemURL
& url
, int permissions
) const {
283 if (!CanHandleType(url
.type()) || !IsAllowedScheme(url
.origin()))
284 return FILE_PERMISSION_ALWAYS_DENY
;
286 if (url
.path().ReferencesParent())
287 return FILE_PERMISSION_ALWAYS_DENY
;
289 // Any write access is disallowed on the root path.
290 if ((url
.path().empty() || VirtualPath::DirName(url
.path()) == url
.path())
291 && (permissions
& ~kReadFilePermissions
))
292 return FILE_PERMISSION_ALWAYS_DENY
;
294 if ((permissions
& kCreateFilePermissions
) == kCreateFilePermissions
) {
295 base::FilePath filename
= VirtualPath::BaseName(url
.path());
296 // See if the name is allowed to create.
297 for (size_t i
= 0; i
< arraysize(kRestrictedNames
); ++i
) {
298 if (filename
.value() == kRestrictedNames
[i
])
299 return FILE_PERMISSION_ALWAYS_DENY
;
301 for (size_t i
= 0; i
< arraysize(kRestrictedChars
); ++i
) {
302 if (filename
.value().find(kRestrictedChars
[i
]) !=
303 base::FilePath::StringType::npos
)
304 return FILE_PERMISSION_ALWAYS_DENY
;
308 // Access to the sandbox directory (and only to the directory) should be
310 return FILE_PERMISSION_ALWAYS_ALLOW
;
313 FileSystemOperation
* SandboxMountPointProvider::CreateFileSystemOperation(
314 const FileSystemURL
& url
,
315 FileSystemContext
* context
,
316 base::PlatformFileError
* error_code
) const {
317 scoped_ptr
<FileSystemOperationContext
> operation_context(
318 new FileSystemOperationContext(context
));
320 // Copy the observer lists (assuming we only have small number of observers).
321 if (url
.type() == kFileSystemTypeSyncable
) {
322 operation_context
->set_update_observers(syncable_update_observers_
);
323 operation_context
->set_change_observers(syncable_change_observers_
);
324 operation_context
->set_access_observers(access_observers_
);
325 return new sync_file_system::SyncableFileSystemOperation(
326 context
, operation_context
.Pass());
329 // For regular sandboxed types.
330 operation_context
->set_update_observers(update_observers_
);
331 operation_context
->set_access_observers(access_observers_
);
332 return new LocalFileSystemOperation(context
, operation_context
.Pass());
335 scoped_ptr
<webkit_blob::FileStreamReader
>
336 SandboxMountPointProvider::CreateFileStreamReader(
337 const FileSystemURL
& url
,
339 const base::Time
& expected_modification_time
,
340 FileSystemContext
* context
) const {
341 return scoped_ptr
<webkit_blob::FileStreamReader
>(
342 new FileSystemFileStreamReader(
343 context
, url
, offset
, expected_modification_time
));
346 scoped_ptr
<fileapi::FileStreamWriter
>
347 SandboxMountPointProvider::CreateFileStreamWriter(
348 const FileSystemURL
& url
,
350 FileSystemContext
* context
) const {
351 return scoped_ptr
<fileapi::FileStreamWriter
>(
352 new SandboxFileStreamWriter(context
, url
, offset
, update_observers_
));
355 FileSystemQuotaUtil
* SandboxMountPointProvider::GetQuotaUtil() {
359 void SandboxMountPointProvider::DeleteFileSystem(
360 const GURL
& origin_url
,
362 FileSystemContext
* context
,
363 const DeleteFileSystemCallback
& callback
) {
364 base::PostTaskAndReplyWithResult(
365 context
->task_runners()->file_task_runner(),
367 // It is safe to pass Unretained(this) since context owns it.
368 base::Bind(&SandboxMountPointProvider::DeleteOriginDataOnFileThread
,
369 base::Unretained(this),
370 make_scoped_refptr(context
),
371 base::Unretained(context
->quota_manager_proxy()),
377 SandboxMountPointProvider::OriginEnumerator
*
378 SandboxMountPointProvider::CreateOriginEnumerator() {
379 return new ObfuscatedOriginEnumerator(sandbox_sync_file_util());
382 base::FilePath
SandboxMountPointProvider::GetBaseDirectoryForOriginAndType(
383 const GURL
& origin_url
, fileapi::FileSystemType type
, bool create
) {
385 base::PlatformFileError error
= base::PLATFORM_FILE_OK
;
386 base::FilePath path
= sandbox_sync_file_util()->GetDirectoryForOriginAndType(
387 origin_url
, type
, create
, &error
);
388 if (error
!= base::PLATFORM_FILE_OK
)
389 return base::FilePath();
393 base::PlatformFileError
394 SandboxMountPointProvider::DeleteOriginDataOnFileThread(
395 FileSystemContext
* file_system_context
,
396 QuotaManagerProxy
* proxy
,
397 const GURL
& origin_url
,
398 fileapi::FileSystemType type
) {
400 int64 usage
= GetOriginUsageOnFileThread(file_system_context
,
403 file_system_usage_cache_
->CloseCacheFiles();
404 bool result
= sandbox_sync_file_util()->DeleteDirectoryForOriginAndType(
406 if (result
&& proxy
) {
407 proxy
->NotifyStorageModified(
408 quota::QuotaClient::kFileSystem
,
410 FileSystemTypeToQuotaStorageType(type
),
415 return base::PLATFORM_FILE_OK
;
416 return base::PLATFORM_FILE_ERROR_FAILED
;
419 void SandboxMountPointProvider::GetOriginsForTypeOnFileThread(
420 fileapi::FileSystemType type
, std::set
<GURL
>* origins
) {
421 DCHECK(CanHandleType(type
));
423 scoped_ptr
<OriginEnumerator
> enumerator(CreateOriginEnumerator());
425 while (!(origin
= enumerator
->Next()).is_empty()) {
426 if (enumerator
->HasFileSystemType(type
))
427 origins
->insert(origin
);
430 case kFileSystemTypeTemporary
:
431 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel
, origins
->size());
433 case kFileSystemTypePersistent
:
434 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel
, origins
->size());
441 void SandboxMountPointProvider::GetOriginsForHostOnFileThread(
442 fileapi::FileSystemType type
, const std::string
& host
,
443 std::set
<GURL
>* origins
) {
444 DCHECK(CanHandleType(type
));
446 scoped_ptr
<OriginEnumerator
> enumerator(CreateOriginEnumerator());
448 while (!(origin
= enumerator
->Next()).is_empty()) {
449 if (host
== net::GetHostOrSpecFromURL(origin
) &&
450 enumerator
->HasFileSystemType(type
))
451 origins
->insert(origin
);
455 int64
SandboxMountPointProvider::GetOriginUsageOnFileThread(
456 FileSystemContext
* file_system_context
,
457 const GURL
& origin_url
,
458 fileapi::FileSystemType type
) {
459 DCHECK(CanHandleType(type
));
460 if (!enable_usage_tracking_
)
463 base::FilePath base_path
=
464 GetBaseDirectoryForOriginAndType(origin_url
, type
, false);
465 if (base_path
.empty() || !file_util::DirectoryExists(base_path
))
467 base::FilePath usage_file_path
=
468 base_path
.Append(FileSystemUsageCache::kUsageFileName
);
470 bool is_valid
= file_system_usage_cache_
->IsValid(usage_file_path
);
471 int32 dirty_status
= file_system_usage_cache_
->GetDirty(usage_file_path
);
472 bool visited
= (visited_origins_
.find(origin_url
) != visited_origins_
.end());
473 visited_origins_
.insert(origin_url
);
474 if (is_valid
&& (dirty_status
== 0 || (dirty_status
> 0 && visited
))) {
475 // The usage cache is clean (dirty == 0) or the origin is already
476 // initialized and running. Read the cache file to get the usage.
477 return file_system_usage_cache_
->GetUsage(usage_file_path
);
479 // The usage cache has not been initialized or the cache is dirty.
480 // Get the directory size now and update the cache.
481 file_system_usage_cache_
->Delete(usage_file_path
);
482 FileSystemOperationContext
context(file_system_context
);
483 FileSystemURL url
= file_system_context
->CreateCrackedFileSystemURL(
484 origin_url
, type
, base::FilePath());
485 scoped_ptr
<FileSystemFileUtil::AbstractFileEnumerator
> enumerator(
486 sandbox_sync_file_util()->CreateFileEnumerator(&context
, url
, true));
488 base::FilePath file_path_each
;
491 while (!(file_path_each
= enumerator
->Next()).empty()) {
492 usage
+= enumerator
->Size();
493 usage
+= ObfuscatedFileUtil::ComputeFilePathCost(file_path_each
);
495 // This clears the dirty flag too.
496 file_system_usage_cache_
->UpdateUsage(usage_file_path
, usage
);
500 void SandboxMountPointProvider::InvalidateUsageCache(
501 const GURL
& origin_url
, fileapi::FileSystemType type
) {
502 DCHECK(CanHandleType(type
));
503 base::PlatformFileError error
= base::PLATFORM_FILE_OK
;
504 base::FilePath usage_file_path
= GetUsageCachePathForOriginAndType(
505 sandbox_sync_file_util(), origin_url
, type
, &error
);
506 if (error
!= base::PLATFORM_FILE_OK
)
508 file_system_usage_cache_
->IncrementDirty(usage_file_path
);
511 void SandboxMountPointProvider::CollectOpenFileSystemMetrics(
512 base::PlatformFileError error_code
) {
513 base::Time now
= base::Time::Now();
514 bool throttled
= now
< next_release_time_for_open_filesystem_stat_
;
516 next_release_time_for_open_filesystem_stat_
=
517 now
+ base::TimeDelta::FromHours(kMinimumStatsCollectionIntervalHours
);
520 #define REPORT(report_value) \
521 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailLabel, \
523 kFileSystemErrorMax); \
525 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailNonThrottledLabel, \
527 kFileSystemErrorMax); \
530 switch (error_code
) {
531 case base::PLATFORM_FILE_OK
:
534 case base::PLATFORM_FILE_ERROR_INVALID_URL
:
535 REPORT(kInvalidSchemeError
);
537 case base::PLATFORM_FILE_ERROR_NOT_FOUND
:
540 case base::PLATFORM_FILE_ERROR_FAILED
:
542 REPORT(kUnknownError
);
548 const UpdateObserverList
* SandboxMountPointProvider::GetUpdateObservers(
549 FileSystemType type
) const {
550 DCHECK(CanHandleType(type
));
551 if (type
== kFileSystemTypeSyncable
)
552 return &syncable_update_observers_
;
553 return &update_observers_
;
556 void SandboxMountPointProvider::AddSyncableFileUpdateObserver(
557 FileUpdateObserver
* observer
,
558 base::SequencedTaskRunner
* task_runner
) {
559 UpdateObserverList::Source observer_source
=
560 syncable_update_observers_
.source();
561 observer_source
.AddObserver(observer
, task_runner
);
562 syncable_update_observers_
= UpdateObserverList(observer_source
);
565 void SandboxMountPointProvider::AddSyncableFileChangeObserver(
566 FileChangeObserver
* observer
,
567 base::SequencedTaskRunner
* task_runner
) {
568 ChangeObserverList::Source observer_source
=
569 syncable_change_observers_
.source();
570 observer_source
.AddObserver(observer
, task_runner
);
571 syncable_change_observers_
= ChangeObserverList(observer_source
);
574 LocalFileSystemOperation
*
575 SandboxMountPointProvider::CreateFileSystemOperationForSync(
576 FileSystemContext
* file_system_context
) {
577 scoped_ptr
<FileSystemOperationContext
> operation_context(
578 new FileSystemOperationContext(file_system_context
));
579 operation_context
->set_update_observers(update_observers_
);
580 operation_context
->set_access_observers(access_observers_
);
581 return new LocalFileSystemOperation(file_system_context
,
582 operation_context
.Pass());
585 base::FilePath
SandboxMountPointProvider::GetUsageCachePathForOriginAndType(
586 const GURL
& origin_url
,
587 FileSystemType type
) {
588 base::PlatformFileError error
;
589 base::FilePath path
= GetUsageCachePathForOriginAndType(
590 sandbox_sync_file_util(), origin_url
, type
, &error
);
591 if (error
!= base::PLATFORM_FILE_OK
)
592 return base::FilePath();
597 base::FilePath
SandboxMountPointProvider::GetUsageCachePathForOriginAndType(
598 ObfuscatedFileUtil
* sandbox_file_util
,
599 const GURL
& origin_url
,
600 fileapi::FileSystemType type
,
601 base::PlatformFileError
* error_out
) {
603 *error_out
= base::PLATFORM_FILE_OK
;
604 base::FilePath base_path
= sandbox_file_util
->GetDirectoryForOriginAndType(
605 origin_url
, type
, false /* create */, error_out
);
606 if (*error_out
!= base::PLATFORM_FILE_OK
)
607 return base::FilePath();
608 return base_path
.Append(FileSystemUsageCache::kUsageFileName
);
611 bool SandboxMountPointProvider::IsAllowedScheme(const GURL
& url
) const {
612 // Basically we only accept http or https. We allow file:// URLs
613 // only if --allow-file-access-from-files flag is given.
614 if (url
.SchemeIs("http") || url
.SchemeIs("https"))
616 if (url
.SchemeIsFileSystem())
617 return url
.inner_url() && IsAllowedScheme(*url
.inner_url());
620 i
< file_system_options_
.additional_allowed_schemes().size();
623 file_system_options_
.additional_allowed_schemes()[i
].c_str()))
629 ObfuscatedFileUtil
* SandboxMountPointProvider::sandbox_sync_file_util() {
630 DCHECK(sandbox_file_util_
.get());
631 return static_cast<ObfuscatedFileUtil
*>(sandbox_file_util_
->sync_file_util());
635 void SandboxMountPointProvider::InvalidateUsageCacheOnFileThread(
636 ObfuscatedFileUtil
* file_util
,
639 FileSystemUsageCache
* usage_cache
) {
640 base::PlatformFileError error
= base::PLATFORM_FILE_OK
;
641 base::FilePath usage_cache_path
= GetUsageCachePathForOriginAndType(
642 file_util
, origin
, type
, &error
);
643 if (error
== base::PLATFORM_FILE_OK
)
644 usage_cache
->IncrementDirty(usage_cache_path
);
647 } // namespace fileapi