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

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

Issue 442383002: Move storage-related files from webkit/ to new top-level directory storage/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 4 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 2013 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_file_system_backend_delegate.h"
6
7 #include <vector>
8
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/metrics/histogram.h"
12 #include "base/stl_util.h"
13 #include "base/task_runner_util.h"
14 #include "net/base/net_util.h"
15 #include "webkit/browser/blob/file_stream_reader.h"
16 #include "webkit/browser/fileapi/async_file_util_adapter.h"
17 #include "webkit/browser/fileapi/file_system_context.h"
18 #include "webkit/browser/fileapi/file_system_operation_context.h"
19 #include "webkit/browser/fileapi/file_system_url.h"
20 #include "webkit/browser/fileapi/file_system_usage_cache.h"
21 #include "webkit/browser/fileapi/obfuscated_file_util.h"
22 #include "webkit/browser/fileapi/quota/quota_backend_impl.h"
23 #include "webkit/browser/fileapi/quota/quota_reservation.h"
24 #include "webkit/browser/fileapi/quota/quota_reservation_manager.h"
25 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h"
26 #include "webkit/browser/fileapi/sandbox_file_system_backend.h"
27 #include "webkit/browser/fileapi/sandbox_quota_observer.h"
28 #include "webkit/browser/quota/quota_manager_proxy.h"
29 #include "webkit/common/fileapi/file_system_util.h"
30
31 namespace fileapi {
32
33 namespace {
34
35 const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount";
36 const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount";
37
38 const char kOpenFileSystemLabel[] = "FileSystem.OpenFileSystem";
39 const char kOpenFileSystemDetailLabel[] = "FileSystem.OpenFileSystemDetail";
40 const char kOpenFileSystemDetailNonThrottledLabel[] =
41 "FileSystem.OpenFileSystemDetailNonthrottled";
42 int64 kMinimumStatsCollectionIntervalHours = 1;
43
44 // For type directory names in ObfuscatedFileUtil.
45 // TODO(kinuko,nhiroki): Each type string registration should be done
46 // via its own backend.
47 const char kTemporaryDirectoryName[] = "t";
48 const char kPersistentDirectoryName[] = "p";
49 const char kSyncableDirectoryName[] = "s";
50
51 const char* kPrepopulateTypes[] = {
52 kPersistentDirectoryName,
53 kTemporaryDirectoryName
54 };
55
56 enum FileSystemError {
57 kOK = 0,
58 kIncognito,
59 kInvalidSchemeError,
60 kCreateDirectoryError,
61 kNotFound,
62 kUnknownError,
63 kFileSystemErrorMax,
64 };
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 std::string GetTypeStringForURL(const FileSystemURL& url) {
78 return SandboxFileSystemBackendDelegate::GetTypeString(url.type());
79 }
80
81 std::set<std::string> GetKnownTypeStrings() {
82 std::set<std::string> known_type_strings;
83 known_type_strings.insert(kTemporaryDirectoryName);
84 known_type_strings.insert(kPersistentDirectoryName);
85 known_type_strings.insert(kSyncableDirectoryName);
86 return known_type_strings;
87 }
88
89 class ObfuscatedOriginEnumerator
90 : public SandboxFileSystemBackendDelegate::OriginEnumerator {
91 public:
92 explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) {
93 enum_.reset(file_util->CreateOriginEnumerator());
94 }
95 virtual ~ObfuscatedOriginEnumerator() {}
96
97 virtual GURL Next() OVERRIDE {
98 return enum_->Next();
99 }
100
101 virtual bool HasFileSystemType(FileSystemType type) const OVERRIDE {
102 return enum_->HasTypeDirectory(
103 SandboxFileSystemBackendDelegate::GetTypeString(type));
104 }
105
106 private:
107 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_;
108 };
109
110 void OpenFileSystemOnFileTaskRunner(
111 ObfuscatedFileUtil* file_util,
112 const GURL& origin_url,
113 FileSystemType type,
114 OpenFileSystemMode mode,
115 base::File::Error* error_ptr) {
116 DCHECK(error_ptr);
117 const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT);
118 file_util->GetDirectoryForOriginAndType(
119 origin_url, SandboxFileSystemBackendDelegate::GetTypeString(type),
120 create, error_ptr);
121 if (*error_ptr != base::File::FILE_OK) {
122 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel,
123 kCreateDirectoryError,
124 kFileSystemErrorMax);
125 } else {
126 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kOK, kFileSystemErrorMax);
127 }
128 // The reference of file_util will be derefed on the FILE thread
129 // when the storage of this callback gets deleted regardless of whether
130 // this method is called or not.
131 }
132
133 void DidOpenFileSystem(
134 base::WeakPtr<SandboxFileSystemBackendDelegate> delegate,
135 const base::Callback<void(base::File::Error error)>& callback,
136 base::File::Error* error) {
137 if (delegate.get())
138 delegate.get()->CollectOpenFileSystemMetrics(*error);
139 callback.Run(*error);
140 }
141
142 template <typename T>
143 void DeleteSoon(base::SequencedTaskRunner* runner, T* ptr) {
144 if (!runner->DeleteSoon(FROM_HERE, ptr))
145 delete ptr;
146 }
147
148 } // namespace
149
150 const base::FilePath::CharType
151 SandboxFileSystemBackendDelegate::kFileSystemDirectory[] =
152 FILE_PATH_LITERAL("File System");
153
154 // static
155 std::string SandboxFileSystemBackendDelegate::GetTypeString(
156 FileSystemType type) {
157 switch (type) {
158 case kFileSystemTypeTemporary:
159 return kTemporaryDirectoryName;
160 case kFileSystemTypePersistent:
161 return kPersistentDirectoryName;
162 case kFileSystemTypeSyncable:
163 case kFileSystemTypeSyncableForInternalSync:
164 return kSyncableDirectoryName;
165 case kFileSystemTypeUnknown:
166 default:
167 NOTREACHED() << "Unknown filesystem type requested:" << type;
168 return std::string();
169 }
170 }
171
172 SandboxFileSystemBackendDelegate::SandboxFileSystemBackendDelegate(
173 quota::QuotaManagerProxy* quota_manager_proxy,
174 base::SequencedTaskRunner* file_task_runner,
175 const base::FilePath& profile_path,
176 quota::SpecialStoragePolicy* special_storage_policy,
177 const FileSystemOptions& file_system_options)
178 : file_task_runner_(file_task_runner),
179 sandbox_file_util_(new AsyncFileUtilAdapter(
180 new ObfuscatedFileUtil(
181 special_storage_policy,
182 profile_path.Append(kFileSystemDirectory),
183 file_system_options.env_override(),
184 file_task_runner,
185 base::Bind(&GetTypeStringForURL),
186 GetKnownTypeStrings(),
187 this))),
188 file_system_usage_cache_(new FileSystemUsageCache(file_task_runner)),
189 quota_observer_(new SandboxQuotaObserver(
190 quota_manager_proxy,
191 file_task_runner,
192 obfuscated_file_util(),
193 usage_cache())),
194 quota_reservation_manager_(new QuotaReservationManager(
195 scoped_ptr<QuotaReservationManager::QuotaBackend>(
196 new QuotaBackendImpl(file_task_runner_,
197 obfuscated_file_util(),
198 usage_cache(),
199 quota_manager_proxy)))),
200 special_storage_policy_(special_storage_policy),
201 file_system_options_(file_system_options),
202 is_filesystem_opened_(false),
203 weak_factory_(this) {
204 // Prepopulate database only if it can run asynchronously (i.e. the current
205 // thread is not file_task_runner). Usually this is the case but may not
206 // in test code.
207 if (!file_system_options.is_incognito() &&
208 !file_task_runner_->RunsTasksOnCurrentThread()) {
209 std::vector<std::string> types_to_prepopulate(
210 &kPrepopulateTypes[0],
211 &kPrepopulateTypes[arraysize(kPrepopulateTypes)]);
212 file_task_runner_->PostTask(
213 FROM_HERE,
214 base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase,
215 base::Unretained(obfuscated_file_util()),
216 types_to_prepopulate));
217 }
218 }
219
220 SandboxFileSystemBackendDelegate::~SandboxFileSystemBackendDelegate() {
221 io_thread_checker_.DetachFromThread();
222
223 if (!file_task_runner_->RunsTasksOnCurrentThread()) {
224 DeleteSoon(file_task_runner_.get(), quota_reservation_manager_.release());
225 DeleteSoon(file_task_runner_.get(), sandbox_file_util_.release());
226 DeleteSoon(file_task_runner_.get(), quota_observer_.release());
227 DeleteSoon(file_task_runner_.get(), file_system_usage_cache_.release());
228 }
229 }
230
231 SandboxFileSystemBackendDelegate::OriginEnumerator*
232 SandboxFileSystemBackendDelegate::CreateOriginEnumerator() {
233 return new ObfuscatedOriginEnumerator(obfuscated_file_util());
234 }
235
236 base::FilePath
237 SandboxFileSystemBackendDelegate::GetBaseDirectoryForOriginAndType(
238 const GURL& origin_url,
239 FileSystemType type,
240 bool create) {
241 base::File::Error error = base::File::FILE_OK;
242 base::FilePath path = obfuscated_file_util()->GetDirectoryForOriginAndType(
243 origin_url, GetTypeString(type), create, &error);
244 if (error != base::File::FILE_OK)
245 return base::FilePath();
246 return path;
247 }
248
249 void SandboxFileSystemBackendDelegate::OpenFileSystem(
250 const GURL& origin_url,
251 FileSystemType type,
252 OpenFileSystemMode mode,
253 const OpenFileSystemCallback& callback,
254 const GURL& root_url) {
255 if (!IsAllowedScheme(origin_url)) {
256 callback.Run(GURL(), std::string(), base::File::FILE_ERROR_SECURITY);
257 return;
258 }
259
260 std::string name = GetFileSystemName(origin_url, type);
261
262 base::File::Error* error_ptr = new base::File::Error;
263 file_task_runner_->PostTaskAndReply(
264 FROM_HERE,
265 base::Bind(&OpenFileSystemOnFileTaskRunner,
266 obfuscated_file_util(), origin_url, type, mode,
267 base::Unretained(error_ptr)),
268 base::Bind(&DidOpenFileSystem,
269 weak_factory_.GetWeakPtr(),
270 base::Bind(callback, root_url, name),
271 base::Owned(error_ptr)));
272
273 io_thread_checker_.DetachFromThread();
274 is_filesystem_opened_ = true;
275 }
276
277 scoped_ptr<FileSystemOperationContext>
278 SandboxFileSystemBackendDelegate::CreateFileSystemOperationContext(
279 const FileSystemURL& url,
280 FileSystemContext* context,
281 base::File::Error* error_code) const {
282 if (!IsAccessValid(url)) {
283 *error_code = base::File::FILE_ERROR_SECURITY;
284 return scoped_ptr<FileSystemOperationContext>();
285 }
286
287 const UpdateObserverList* update_observers = GetUpdateObservers(url.type());
288 const ChangeObserverList* change_observers = GetChangeObservers(url.type());
289 DCHECK(update_observers);
290
291 scoped_ptr<FileSystemOperationContext> operation_context(
292 new FileSystemOperationContext(context));
293 operation_context->set_update_observers(*update_observers);
294 operation_context->set_change_observers(
295 change_observers ? *change_observers : ChangeObserverList());
296
297 return operation_context.Pass();
298 }
299
300 scoped_ptr<webkit_blob::FileStreamReader>
301 SandboxFileSystemBackendDelegate::CreateFileStreamReader(
302 const FileSystemURL& url,
303 int64 offset,
304 const base::Time& expected_modification_time,
305 FileSystemContext* context) const {
306 if (!IsAccessValid(url))
307 return scoped_ptr<webkit_blob::FileStreamReader>();
308 return scoped_ptr<webkit_blob::FileStreamReader>(
309 webkit_blob::FileStreamReader::CreateForFileSystemFile(
310 context, url, offset, expected_modification_time));
311 }
312
313 scoped_ptr<FileStreamWriter>
314 SandboxFileSystemBackendDelegate::CreateFileStreamWriter(
315 const FileSystemURL& url,
316 int64 offset,
317 FileSystemContext* context,
318 FileSystemType type) const {
319 if (!IsAccessValid(url))
320 return scoped_ptr<FileStreamWriter>();
321 const UpdateObserverList* observers = GetUpdateObservers(type);
322 DCHECK(observers);
323 return scoped_ptr<FileStreamWriter>(
324 new SandboxFileStreamWriter(context, url, offset, *observers));
325 }
326
327 base::File::Error
328 SandboxFileSystemBackendDelegate::DeleteOriginDataOnFileTaskRunner(
329 FileSystemContext* file_system_context,
330 quota::QuotaManagerProxy* proxy,
331 const GURL& origin_url,
332 FileSystemType type) {
333 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
334 int64 usage = GetOriginUsageOnFileTaskRunner(
335 file_system_context, origin_url, type);
336 usage_cache()->CloseCacheFiles();
337 bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType(
338 origin_url, GetTypeString(type));
339 if (result && proxy) {
340 proxy->NotifyStorageModified(
341 quota::QuotaClient::kFileSystem,
342 origin_url,
343 FileSystemTypeToQuotaStorageType(type),
344 -usage);
345 }
346
347 if (result)
348 return base::File::FILE_OK;
349 return base::File::FILE_ERROR_FAILED;
350 }
351
352 void SandboxFileSystemBackendDelegate::GetOriginsForTypeOnFileTaskRunner(
353 FileSystemType type, std::set<GURL>* origins) {
354 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
355 DCHECK(origins);
356 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator());
357 GURL origin;
358 while (!(origin = enumerator->Next()).is_empty()) {
359 if (enumerator->HasFileSystemType(type))
360 origins->insert(origin);
361 }
362 switch (type) {
363 case kFileSystemTypeTemporary:
364 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size());
365 break;
366 case kFileSystemTypePersistent:
367 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size());
368 break;
369 default:
370 break;
371 }
372 }
373
374 void SandboxFileSystemBackendDelegate::GetOriginsForHostOnFileTaskRunner(
375 FileSystemType type, const std::string& host,
376 std::set<GURL>* origins) {
377 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
378 DCHECK(origins);
379 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator());
380 GURL origin;
381 while (!(origin = enumerator->Next()).is_empty()) {
382 if (host == net::GetHostOrSpecFromURL(origin) &&
383 enumerator->HasFileSystemType(type))
384 origins->insert(origin);
385 }
386 }
387
388 int64 SandboxFileSystemBackendDelegate::GetOriginUsageOnFileTaskRunner(
389 FileSystemContext* file_system_context,
390 const GURL& origin_url,
391 FileSystemType type) {
392 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
393
394 // Don't use usage cache and return recalculated usage for sticky invalidated
395 // origins.
396 if (ContainsKey(sticky_dirty_origins_, std::make_pair(origin_url, type)))
397 return RecalculateUsage(file_system_context, origin_url, type);
398
399 base::FilePath base_path =
400 GetBaseDirectoryForOriginAndType(origin_url, type, false);
401 if (base_path.empty() || !base::DirectoryExists(base_path))
402 return 0;
403 base::FilePath usage_file_path =
404 base_path.Append(FileSystemUsageCache::kUsageFileName);
405
406 bool is_valid = usage_cache()->IsValid(usage_file_path);
407 uint32 dirty_status = 0;
408 bool dirty_status_available =
409 usage_cache()->GetDirty(usage_file_path, &dirty_status);
410 bool visited = !visited_origins_.insert(origin_url).second;
411 if (is_valid && (dirty_status == 0 || (dirty_status_available && visited))) {
412 // The usage cache is clean (dirty == 0) or the origin is already
413 // initialized and running. Read the cache file to get the usage.
414 int64 usage = 0;
415 return usage_cache()->GetUsage(usage_file_path, &usage) ? usage : -1;
416 }
417 // The usage cache has not been initialized or the cache is dirty.
418 // Get the directory size now and update the cache.
419 usage_cache()->Delete(usage_file_path);
420
421 int64 usage = RecalculateUsage(file_system_context, origin_url, type);
422
423 // This clears the dirty flag too.
424 usage_cache()->UpdateUsage(usage_file_path, usage);
425 return usage;
426 }
427
428 scoped_refptr<QuotaReservation>
429 SandboxFileSystemBackendDelegate::CreateQuotaReservationOnFileTaskRunner(
430 const GURL& origin,
431 FileSystemType type) {
432 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
433 DCHECK(quota_reservation_manager_);
434 return quota_reservation_manager_->CreateReservation(origin, type);
435 }
436
437 void SandboxFileSystemBackendDelegate::AddFileUpdateObserver(
438 FileSystemType type,
439 FileUpdateObserver* observer,
440 base::SequencedTaskRunner* task_runner) {
441 DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread());
442 update_observers_[type] =
443 update_observers_[type].AddObserver(observer, task_runner);
444 }
445
446 void SandboxFileSystemBackendDelegate::AddFileChangeObserver(
447 FileSystemType type,
448 FileChangeObserver* observer,
449 base::SequencedTaskRunner* task_runner) {
450 DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread());
451 change_observers_[type] =
452 change_observers_[type].AddObserver(observer, task_runner);
453 }
454
455 void SandboxFileSystemBackendDelegate::AddFileAccessObserver(
456 FileSystemType type,
457 FileAccessObserver* observer,
458 base::SequencedTaskRunner* task_runner) {
459 DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread());
460 access_observers_[type] =
461 access_observers_[type].AddObserver(observer, task_runner);
462 }
463
464 const UpdateObserverList* SandboxFileSystemBackendDelegate::GetUpdateObservers(
465 FileSystemType type) const {
466 std::map<FileSystemType, UpdateObserverList>::const_iterator iter =
467 update_observers_.find(type);
468 if (iter == update_observers_.end())
469 return NULL;
470 return &iter->second;
471 }
472
473 const ChangeObserverList* SandboxFileSystemBackendDelegate::GetChangeObservers(
474 FileSystemType type) const {
475 std::map<FileSystemType, ChangeObserverList>::const_iterator iter =
476 change_observers_.find(type);
477 if (iter == change_observers_.end())
478 return NULL;
479 return &iter->second;
480 }
481
482 const AccessObserverList* SandboxFileSystemBackendDelegate::GetAccessObservers(
483 FileSystemType type) const {
484 std::map<FileSystemType, AccessObserverList>::const_iterator iter =
485 access_observers_.find(type);
486 if (iter == access_observers_.end())
487 return NULL;
488 return &iter->second;
489 }
490
491 void SandboxFileSystemBackendDelegate::RegisterQuotaUpdateObserver(
492 FileSystemType type) {
493 AddFileUpdateObserver(type, quota_observer_.get(), file_task_runner_.get());
494 }
495
496 void SandboxFileSystemBackendDelegate::InvalidateUsageCache(
497 const GURL& origin,
498 FileSystemType type) {
499 base::File::Error error = base::File::FILE_OK;
500 base::FilePath usage_file_path = GetUsageCachePathForOriginAndType(
501 obfuscated_file_util(), origin, type, &error);
502 if (error != base::File::FILE_OK)
503 return;
504 usage_cache()->IncrementDirty(usage_file_path);
505 }
506
507 void SandboxFileSystemBackendDelegate::StickyInvalidateUsageCache(
508 const GURL& origin,
509 FileSystemType type) {
510 sticky_dirty_origins_.insert(std::make_pair(origin, type));
511 quota_observer()->SetUsageCacheEnabled(origin, type, false);
512 InvalidateUsageCache(origin, type);
513 }
514
515 FileSystemFileUtil* SandboxFileSystemBackendDelegate::sync_file_util() {
516 return static_cast<AsyncFileUtilAdapter*>(file_util())->sync_file_util();
517 }
518
519 bool SandboxFileSystemBackendDelegate::IsAccessValid(
520 const FileSystemURL& url) const {
521 if (!IsAllowedScheme(url.origin()))
522 return false;
523
524 if (url.path().ReferencesParent())
525 return false;
526
527 // Return earlier if the path is '/', because VirtualPath::BaseName()
528 // returns '/' for '/' and we fail the "basename != '/'" check below.
529 // (We exclude '.' because it's disallowed by spec.)
530 if (VirtualPath::IsRootPath(url.path()) &&
531 url.path() != base::FilePath(base::FilePath::kCurrentDirectory))
532 return true;
533
534 // Restricted names specified in
535 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restriction s
536 base::FilePath filename = VirtualPath::BaseName(url.path());
537 // See if the name is allowed to create.
538 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
539 if (filename.value() == kRestrictedNames[i])
540 return false;
541 }
542 for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
543 if (filename.value().find(kRestrictedChars[i]) !=
544 base::FilePath::StringType::npos)
545 return false;
546 }
547
548 return true;
549 }
550
551 bool SandboxFileSystemBackendDelegate::IsAllowedScheme(const GURL& url) const {
552 // Basically we only accept http or https. We allow file:// URLs
553 // only if --allow-file-access-from-files flag is given.
554 if (url.SchemeIsHTTPOrHTTPS())
555 return true;
556 if (url.SchemeIsFileSystem())
557 return url.inner_url() && IsAllowedScheme(*url.inner_url());
558
559 for (size_t i = 0;
560 i < file_system_options_.additional_allowed_schemes().size();
561 ++i) {
562 if (url.SchemeIs(
563 file_system_options_.additional_allowed_schemes()[i].c_str()))
564 return true;
565 }
566 return false;
567 }
568
569 base::FilePath
570 SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType(
571 const GURL& origin_url,
572 FileSystemType type) {
573 base::File::Error error;
574 base::FilePath path = GetUsageCachePathForOriginAndType(
575 obfuscated_file_util(), origin_url, type, &error);
576 if (error != base::File::FILE_OK)
577 return base::FilePath();
578 return path;
579 }
580
581 // static
582 base::FilePath
583 SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType(
584 ObfuscatedFileUtil* sandbox_file_util,
585 const GURL& origin_url,
586 FileSystemType type,
587 base::File::Error* error_out) {
588 DCHECK(error_out);
589 *error_out = base::File::FILE_OK;
590 base::FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType(
591 origin_url, GetTypeString(type), false /* create */, error_out);
592 if (*error_out != base::File::FILE_OK)
593 return base::FilePath();
594 return base_path.Append(FileSystemUsageCache::kUsageFileName);
595 }
596
597 int64 SandboxFileSystemBackendDelegate::RecalculateUsage(
598 FileSystemContext* context,
599 const GURL& origin,
600 FileSystemType type) {
601 FileSystemOperationContext operation_context(context);
602 FileSystemURL url = context->CreateCrackedFileSystemURL(
603 origin, type, base::FilePath());
604 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator(
605 obfuscated_file_util()->CreateFileEnumerator(
606 &operation_context, url, true));
607
608 base::FilePath file_path_each;
609 int64 usage = 0;
610
611 while (!(file_path_each = enumerator->Next()).empty()) {
612 usage += enumerator->Size();
613 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each);
614 }
615
616 return usage;
617 }
618
619 void SandboxFileSystemBackendDelegate::CollectOpenFileSystemMetrics(
620 base::File::Error error_code) {
621 base::Time now = base::Time::Now();
622 bool throttled = now < next_release_time_for_open_filesystem_stat_;
623 if (!throttled) {
624 next_release_time_for_open_filesystem_stat_ =
625 now + base::TimeDelta::FromHours(kMinimumStatsCollectionIntervalHours);
626 }
627
628 #define REPORT(report_value) \
629 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailLabel, \
630 (report_value), \
631 kFileSystemErrorMax); \
632 if (!throttled) { \
633 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailNonThrottledLabel, \
634 (report_value), \
635 kFileSystemErrorMax); \
636 }
637
638 switch (error_code) {
639 case base::File::FILE_OK:
640 REPORT(kOK);
641 break;
642 case base::File::FILE_ERROR_INVALID_URL:
643 REPORT(kInvalidSchemeError);
644 break;
645 case base::File::FILE_ERROR_NOT_FOUND:
646 REPORT(kNotFound);
647 break;
648 case base::File::FILE_ERROR_FAILED:
649 default:
650 REPORT(kUnknownError);
651 break;
652 }
653 #undef REPORT
654 }
655
656 ObfuscatedFileUtil* SandboxFileSystemBackendDelegate::obfuscated_file_util() {
657 return static_cast<ObfuscatedFileUtil*>(sync_file_util());
658 }
659
660 // Declared in obfuscated_file_util.h.
661 // static
662 ObfuscatedFileUtil* ObfuscatedFileUtil::CreateForTesting(
663 quota::SpecialStoragePolicy* special_storage_policy,
664 const base::FilePath& file_system_directory,
665 leveldb::Env* env_override,
666 base::SequencedTaskRunner* file_task_runner) {
667 return new ObfuscatedFileUtil(special_storage_policy,
668 file_system_directory,
669 env_override,
670 file_task_runner,
671 base::Bind(&GetTypeStringForURL),
672 GetKnownTypeStrings(),
673 NULL);
674 }
675
676 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698