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

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

Issue 539143002: Migrate webkit/browser/ to storage/browser/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix android build Created 6 years, 3 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
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/files/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 storage {
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 storage::QuotaManagerProxy* quota_manager_proxy,
174 base::SequencedTaskRunner* file_task_runner,
175 const base::FilePath& profile_path,
176 storage::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(special_storage_policy,
181 profile_path.Append(kFileSystemDirectory),
182 file_system_options.env_override(),
183 file_task_runner,
184 base::Bind(&GetTypeStringForURL),
185 GetKnownTypeStrings(),
186 this))),
187 file_system_usage_cache_(new FileSystemUsageCache(file_task_runner)),
188 quota_observer_(new SandboxQuotaObserver(quota_manager_proxy,
189 file_task_runner,
190 obfuscated_file_util(),
191 usage_cache())),
192 quota_reservation_manager_(new QuotaReservationManager(
193 scoped_ptr<QuotaReservationManager::QuotaBackend>(
194 new QuotaBackendImpl(file_task_runner_.get(),
195 obfuscated_file_util(),
196 usage_cache(),
197 quota_manager_proxy)))),
198 special_storage_policy_(special_storage_policy),
199 file_system_options_(file_system_options),
200 is_filesystem_opened_(false),
201 weak_factory_(this) {
202 // Prepopulate database only if it can run asynchronously (i.e. the current
203 // thread is not file_task_runner). Usually this is the case but may not
204 // in test code.
205 if (!file_system_options.is_incognito() &&
206 !file_task_runner_->RunsTasksOnCurrentThread()) {
207 std::vector<std::string> types_to_prepopulate(
208 &kPrepopulateTypes[0],
209 &kPrepopulateTypes[arraysize(kPrepopulateTypes)]);
210 file_task_runner_->PostTask(
211 FROM_HERE,
212 base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase,
213 base::Unretained(obfuscated_file_util()),
214 types_to_prepopulate));
215 }
216 }
217
218 SandboxFileSystemBackendDelegate::~SandboxFileSystemBackendDelegate() {
219 io_thread_checker_.DetachFromThread();
220
221 if (!file_task_runner_->RunsTasksOnCurrentThread()) {
222 DeleteSoon(file_task_runner_.get(), quota_reservation_manager_.release());
223 DeleteSoon(file_task_runner_.get(), sandbox_file_util_.release());
224 DeleteSoon(file_task_runner_.get(), quota_observer_.release());
225 DeleteSoon(file_task_runner_.get(), file_system_usage_cache_.release());
226 }
227 }
228
229 SandboxFileSystemBackendDelegate::OriginEnumerator*
230 SandboxFileSystemBackendDelegate::CreateOriginEnumerator() {
231 return new ObfuscatedOriginEnumerator(obfuscated_file_util());
232 }
233
234 base::FilePath
235 SandboxFileSystemBackendDelegate::GetBaseDirectoryForOriginAndType(
236 const GURL& origin_url,
237 FileSystemType type,
238 bool create) {
239 base::File::Error error = base::File::FILE_OK;
240 base::FilePath path = obfuscated_file_util()->GetDirectoryForOriginAndType(
241 origin_url, GetTypeString(type), create, &error);
242 if (error != base::File::FILE_OK)
243 return base::FilePath();
244 return path;
245 }
246
247 void SandboxFileSystemBackendDelegate::OpenFileSystem(
248 const GURL& origin_url,
249 FileSystemType type,
250 OpenFileSystemMode mode,
251 const OpenFileSystemCallback& callback,
252 const GURL& root_url) {
253 if (!IsAllowedScheme(origin_url)) {
254 callback.Run(GURL(), std::string(), base::File::FILE_ERROR_SECURITY);
255 return;
256 }
257
258 std::string name = GetFileSystemName(origin_url, type);
259
260 base::File::Error* error_ptr = new base::File::Error;
261 file_task_runner_->PostTaskAndReply(
262 FROM_HERE,
263 base::Bind(&OpenFileSystemOnFileTaskRunner,
264 obfuscated_file_util(), origin_url, type, mode,
265 base::Unretained(error_ptr)),
266 base::Bind(&DidOpenFileSystem,
267 weak_factory_.GetWeakPtr(),
268 base::Bind(callback, root_url, name),
269 base::Owned(error_ptr)));
270
271 io_thread_checker_.DetachFromThread();
272 is_filesystem_opened_ = true;
273 }
274
275 scoped_ptr<FileSystemOperationContext>
276 SandboxFileSystemBackendDelegate::CreateFileSystemOperationContext(
277 const FileSystemURL& url,
278 FileSystemContext* context,
279 base::File::Error* error_code) const {
280 if (!IsAccessValid(url)) {
281 *error_code = base::File::FILE_ERROR_SECURITY;
282 return scoped_ptr<FileSystemOperationContext>();
283 }
284
285 const UpdateObserverList* update_observers = GetUpdateObservers(url.type());
286 const ChangeObserverList* change_observers = GetChangeObservers(url.type());
287 DCHECK(update_observers);
288
289 scoped_ptr<FileSystemOperationContext> operation_context(
290 new FileSystemOperationContext(context));
291 operation_context->set_update_observers(*update_observers);
292 operation_context->set_change_observers(
293 change_observers ? *change_observers : ChangeObserverList());
294
295 return operation_context.Pass();
296 }
297
298 scoped_ptr<storage::FileStreamReader>
299 SandboxFileSystemBackendDelegate::CreateFileStreamReader(
300 const FileSystemURL& url,
301 int64 offset,
302 const base::Time& expected_modification_time,
303 FileSystemContext* context) const {
304 if (!IsAccessValid(url))
305 return scoped_ptr<storage::FileStreamReader>();
306 return scoped_ptr<storage::FileStreamReader>(
307 storage::FileStreamReader::CreateForFileSystemFile(
308 context, url, offset, expected_modification_time));
309 }
310
311 scoped_ptr<FileStreamWriter>
312 SandboxFileSystemBackendDelegate::CreateFileStreamWriter(
313 const FileSystemURL& url,
314 int64 offset,
315 FileSystemContext* context,
316 FileSystemType type) const {
317 if (!IsAccessValid(url))
318 return scoped_ptr<FileStreamWriter>();
319 const UpdateObserverList* observers = GetUpdateObservers(type);
320 DCHECK(observers);
321 return scoped_ptr<FileStreamWriter>(
322 new SandboxFileStreamWriter(context, url, offset, *observers));
323 }
324
325 base::File::Error
326 SandboxFileSystemBackendDelegate::DeleteOriginDataOnFileTaskRunner(
327 FileSystemContext* file_system_context,
328 storage::QuotaManagerProxy* proxy,
329 const GURL& origin_url,
330 FileSystemType type) {
331 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
332 int64 usage = GetOriginUsageOnFileTaskRunner(
333 file_system_context, origin_url, type);
334 usage_cache()->CloseCacheFiles();
335 bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType(
336 origin_url, GetTypeString(type));
337 if (result && proxy) {
338 proxy->NotifyStorageModified(storage::QuotaClient::kFileSystem,
339 origin_url,
340 FileSystemTypeToQuotaStorageType(type),
341 -usage);
342 }
343
344 if (result)
345 return base::File::FILE_OK;
346 return base::File::FILE_ERROR_FAILED;
347 }
348
349 void SandboxFileSystemBackendDelegate::GetOriginsForTypeOnFileTaskRunner(
350 FileSystemType type, std::set<GURL>* origins) {
351 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
352 DCHECK(origins);
353 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator());
354 GURL origin;
355 while (!(origin = enumerator->Next()).is_empty()) {
356 if (enumerator->HasFileSystemType(type))
357 origins->insert(origin);
358 }
359 switch (type) {
360 case kFileSystemTypeTemporary:
361 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size());
362 break;
363 case kFileSystemTypePersistent:
364 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size());
365 break;
366 default:
367 break;
368 }
369 }
370
371 void SandboxFileSystemBackendDelegate::GetOriginsForHostOnFileTaskRunner(
372 FileSystemType type, const std::string& host,
373 std::set<GURL>* origins) {
374 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
375 DCHECK(origins);
376 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator());
377 GURL origin;
378 while (!(origin = enumerator->Next()).is_empty()) {
379 if (host == net::GetHostOrSpecFromURL(origin) &&
380 enumerator->HasFileSystemType(type))
381 origins->insert(origin);
382 }
383 }
384
385 int64 SandboxFileSystemBackendDelegate::GetOriginUsageOnFileTaskRunner(
386 FileSystemContext* file_system_context,
387 const GURL& origin_url,
388 FileSystemType type) {
389 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
390
391 // Don't use usage cache and return recalculated usage for sticky invalidated
392 // origins.
393 if (ContainsKey(sticky_dirty_origins_, std::make_pair(origin_url, type)))
394 return RecalculateUsage(file_system_context, origin_url, type);
395
396 base::FilePath base_path =
397 GetBaseDirectoryForOriginAndType(origin_url, type, false);
398 if (base_path.empty() || !base::DirectoryExists(base_path))
399 return 0;
400 base::FilePath usage_file_path =
401 base_path.Append(FileSystemUsageCache::kUsageFileName);
402
403 bool is_valid = usage_cache()->IsValid(usage_file_path);
404 uint32 dirty_status = 0;
405 bool dirty_status_available =
406 usage_cache()->GetDirty(usage_file_path, &dirty_status);
407 bool visited = !visited_origins_.insert(origin_url).second;
408 if (is_valid && (dirty_status == 0 || (dirty_status_available && visited))) {
409 // The usage cache is clean (dirty == 0) or the origin is already
410 // initialized and running. Read the cache file to get the usage.
411 int64 usage = 0;
412 return usage_cache()->GetUsage(usage_file_path, &usage) ? usage : -1;
413 }
414 // The usage cache has not been initialized or the cache is dirty.
415 // Get the directory size now and update the cache.
416 usage_cache()->Delete(usage_file_path);
417
418 int64 usage = RecalculateUsage(file_system_context, origin_url, type);
419
420 // This clears the dirty flag too.
421 usage_cache()->UpdateUsage(usage_file_path, usage);
422 return usage;
423 }
424
425 scoped_refptr<QuotaReservation>
426 SandboxFileSystemBackendDelegate::CreateQuotaReservationOnFileTaskRunner(
427 const GURL& origin,
428 FileSystemType type) {
429 DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
430 DCHECK(quota_reservation_manager_);
431 return quota_reservation_manager_->CreateReservation(origin, type);
432 }
433
434 void SandboxFileSystemBackendDelegate::AddFileUpdateObserver(
435 FileSystemType type,
436 FileUpdateObserver* observer,
437 base::SequencedTaskRunner* task_runner) {
438 DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread());
439 update_observers_[type] =
440 update_observers_[type].AddObserver(observer, task_runner);
441 }
442
443 void SandboxFileSystemBackendDelegate::AddFileChangeObserver(
444 FileSystemType type,
445 FileChangeObserver* observer,
446 base::SequencedTaskRunner* task_runner) {
447 DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread());
448 change_observers_[type] =
449 change_observers_[type].AddObserver(observer, task_runner);
450 }
451
452 void SandboxFileSystemBackendDelegate::AddFileAccessObserver(
453 FileSystemType type,
454 FileAccessObserver* observer,
455 base::SequencedTaskRunner* task_runner) {
456 DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread());
457 access_observers_[type] =
458 access_observers_[type].AddObserver(observer, task_runner);
459 }
460
461 const UpdateObserverList* SandboxFileSystemBackendDelegate::GetUpdateObservers(
462 FileSystemType type) const {
463 std::map<FileSystemType, UpdateObserverList>::const_iterator iter =
464 update_observers_.find(type);
465 if (iter == update_observers_.end())
466 return NULL;
467 return &iter->second;
468 }
469
470 const ChangeObserverList* SandboxFileSystemBackendDelegate::GetChangeObservers(
471 FileSystemType type) const {
472 std::map<FileSystemType, ChangeObserverList>::const_iterator iter =
473 change_observers_.find(type);
474 if (iter == change_observers_.end())
475 return NULL;
476 return &iter->second;
477 }
478
479 const AccessObserverList* SandboxFileSystemBackendDelegate::GetAccessObservers(
480 FileSystemType type) const {
481 std::map<FileSystemType, AccessObserverList>::const_iterator iter =
482 access_observers_.find(type);
483 if (iter == access_observers_.end())
484 return NULL;
485 return &iter->second;
486 }
487
488 void SandboxFileSystemBackendDelegate::RegisterQuotaUpdateObserver(
489 FileSystemType type) {
490 AddFileUpdateObserver(type, quota_observer_.get(), file_task_runner_.get());
491 }
492
493 void SandboxFileSystemBackendDelegate::InvalidateUsageCache(
494 const GURL& origin,
495 FileSystemType type) {
496 base::File::Error error = base::File::FILE_OK;
497 base::FilePath usage_file_path = GetUsageCachePathForOriginAndType(
498 obfuscated_file_util(), origin, type, &error);
499 if (error != base::File::FILE_OK)
500 return;
501 usage_cache()->IncrementDirty(usage_file_path);
502 }
503
504 void SandboxFileSystemBackendDelegate::StickyInvalidateUsageCache(
505 const GURL& origin,
506 FileSystemType type) {
507 sticky_dirty_origins_.insert(std::make_pair(origin, type));
508 quota_observer()->SetUsageCacheEnabled(origin, type, false);
509 InvalidateUsageCache(origin, type);
510 }
511
512 FileSystemFileUtil* SandboxFileSystemBackendDelegate::sync_file_util() {
513 return static_cast<AsyncFileUtilAdapter*>(file_util())->sync_file_util();
514 }
515
516 bool SandboxFileSystemBackendDelegate::IsAccessValid(
517 const FileSystemURL& url) const {
518 if (!IsAllowedScheme(url.origin()))
519 return false;
520
521 if (url.path().ReferencesParent())
522 return false;
523
524 // Return earlier if the path is '/', because VirtualPath::BaseName()
525 // returns '/' for '/' and we fail the "basename != '/'" check below.
526 // (We exclude '.' because it's disallowed by spec.)
527 if (VirtualPath::IsRootPath(url.path()) &&
528 url.path() != base::FilePath(base::FilePath::kCurrentDirectory))
529 return true;
530
531 // Restricted names specified in
532 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restriction s
533 base::FilePath filename = VirtualPath::BaseName(url.path());
534 // See if the name is allowed to create.
535 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
536 if (filename.value() == kRestrictedNames[i])
537 return false;
538 }
539 for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
540 if (filename.value().find(kRestrictedChars[i]) !=
541 base::FilePath::StringType::npos)
542 return false;
543 }
544
545 return true;
546 }
547
548 bool SandboxFileSystemBackendDelegate::IsAllowedScheme(const GURL& url) const {
549 // Basically we only accept http or https. We allow file:// URLs
550 // only if --allow-file-access-from-files flag is given.
551 if (url.SchemeIsHTTPOrHTTPS())
552 return true;
553 if (url.SchemeIsFileSystem())
554 return url.inner_url() && IsAllowedScheme(*url.inner_url());
555
556 for (size_t i = 0;
557 i < file_system_options_.additional_allowed_schemes().size();
558 ++i) {
559 if (url.SchemeIs(
560 file_system_options_.additional_allowed_schemes()[i].c_str()))
561 return true;
562 }
563 return false;
564 }
565
566 base::FilePath
567 SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType(
568 const GURL& origin_url,
569 FileSystemType type) {
570 base::File::Error error;
571 base::FilePath path = GetUsageCachePathForOriginAndType(
572 obfuscated_file_util(), origin_url, type, &error);
573 if (error != base::File::FILE_OK)
574 return base::FilePath();
575 return path;
576 }
577
578 // static
579 base::FilePath
580 SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType(
581 ObfuscatedFileUtil* sandbox_file_util,
582 const GURL& origin_url,
583 FileSystemType type,
584 base::File::Error* error_out) {
585 DCHECK(error_out);
586 *error_out = base::File::FILE_OK;
587 base::FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType(
588 origin_url, GetTypeString(type), false /* create */, error_out);
589 if (*error_out != base::File::FILE_OK)
590 return base::FilePath();
591 return base_path.Append(FileSystemUsageCache::kUsageFileName);
592 }
593
594 int64 SandboxFileSystemBackendDelegate::RecalculateUsage(
595 FileSystemContext* context,
596 const GURL& origin,
597 FileSystemType type) {
598 FileSystemOperationContext operation_context(context);
599 FileSystemURL url = context->CreateCrackedFileSystemURL(
600 origin, type, base::FilePath());
601 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator(
602 obfuscated_file_util()->CreateFileEnumerator(
603 &operation_context, url, true));
604
605 base::FilePath file_path_each;
606 int64 usage = 0;
607
608 while (!(file_path_each = enumerator->Next()).empty()) {
609 usage += enumerator->Size();
610 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each);
611 }
612
613 return usage;
614 }
615
616 void SandboxFileSystemBackendDelegate::CollectOpenFileSystemMetrics(
617 base::File::Error error_code) {
618 base::Time now = base::Time::Now();
619 bool throttled = now < next_release_time_for_open_filesystem_stat_;
620 if (!throttled) {
621 next_release_time_for_open_filesystem_stat_ =
622 now + base::TimeDelta::FromHours(kMinimumStatsCollectionIntervalHours);
623 }
624
625 #define REPORT(report_value) \
626 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailLabel, \
627 (report_value), \
628 kFileSystemErrorMax); \
629 if (!throttled) { \
630 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemDetailNonThrottledLabel, \
631 (report_value), \
632 kFileSystemErrorMax); \
633 }
634
635 switch (error_code) {
636 case base::File::FILE_OK:
637 REPORT(kOK);
638 break;
639 case base::File::FILE_ERROR_INVALID_URL:
640 REPORT(kInvalidSchemeError);
641 break;
642 case base::File::FILE_ERROR_NOT_FOUND:
643 REPORT(kNotFound);
644 break;
645 case base::File::FILE_ERROR_FAILED:
646 default:
647 REPORT(kUnknownError);
648 break;
649 }
650 #undef REPORT
651 }
652
653 ObfuscatedFileUtil* SandboxFileSystemBackendDelegate::obfuscated_file_util() {
654 return static_cast<ObfuscatedFileUtil*>(sync_file_util());
655 }
656
657 // Declared in obfuscated_file_util.h.
658 // static
659 ObfuscatedFileUtil* ObfuscatedFileUtil::CreateForTesting(
660 storage::SpecialStoragePolicy* special_storage_policy,
661 const base::FilePath& file_system_directory,
662 leveldb::Env* env_override,
663 base::SequencedTaskRunner* file_task_runner) {
664 return new ObfuscatedFileUtil(special_storage_policy,
665 file_system_directory,
666 env_override,
667 file_task_runner,
668 base::Bind(&GetTypeStringForURL),
669 GetKnownTypeStrings(),
670 NULL);
671 }
672
673 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698