• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "content/browser/renderer_host/pepper/quota_reservation.h"
6 
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "storage/browser/fileapi/file_system_operation_runner.h"
11 #include "storage/browser/fileapi/quota/open_file_handle.h"
12 #include "storage/browser/fileapi/quota/quota_reservation.h"
13 #include "storage/common/fileapi/file_system_util.h"
14 
15 namespace content {
16 
17 // static
Create(scoped_refptr<storage::FileSystemContext> file_system_context,const GURL & origin_url,storage::FileSystemType type)18 scoped_refptr<QuotaReservation> QuotaReservation::Create(
19     scoped_refptr<storage::FileSystemContext> file_system_context,
20     const GURL& origin_url,
21     storage::FileSystemType type) {
22   return scoped_refptr<QuotaReservation>(
23       new QuotaReservation(file_system_context, origin_url, type));
24 }
25 
QuotaReservation(scoped_refptr<storage::FileSystemContext> file_system_context,const GURL & origin_url,storage::FileSystemType file_system_type)26 QuotaReservation::QuotaReservation(
27     scoped_refptr<storage::FileSystemContext> file_system_context,
28     const GURL& origin_url,
29     storage::FileSystemType file_system_type)
30     : file_system_context_(file_system_context) {
31   quota_reservation_ =
32       file_system_context->CreateQuotaReservationOnFileTaskRunner(
33           origin_url, file_system_type);
34 }
35 
36 // For unit testing only.
QuotaReservation(scoped_refptr<storage::QuotaReservation> quota_reservation,const GURL &,storage::FileSystemType)37 QuotaReservation::QuotaReservation(
38     scoped_refptr<storage::QuotaReservation> quota_reservation,
39     const GURL& /* origin_url */,
40     storage::FileSystemType /* file_system_type */)
41     : quota_reservation_(quota_reservation) {
42 }
43 
~QuotaReservation()44 QuotaReservation::~QuotaReservation() {
45   // We should have no open files at this point.
46   DCHECK(files_.size() == 0);
47   for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it)
48     delete it->second;
49 }
50 
OpenFile(int32_t id,const storage::FileSystemURL & url)51 int64_t QuotaReservation::OpenFile(int32_t id,
52                                    const storage::FileSystemURL& url) {
53   base::FilePath platform_file_path;
54   if (file_system_context_.get()) {
55     base::File::Error error =
56         file_system_context_->operation_runner()->SyncGetPlatformPath(
57             url, &platform_file_path);
58     if (error != base::File::FILE_OK) {
59       NOTREACHED();
60       return 0;
61     }
62   } else {
63     // For test.
64     platform_file_path = url.path();
65   }
66 
67   scoped_ptr<storage::OpenFileHandle> file_handle =
68       quota_reservation_->GetOpenFileHandle(platform_file_path);
69   std::pair<FileMap::iterator, bool> insert_result =
70       files_.insert(std::make_pair(id, file_handle.get()));
71   if (insert_result.second) {
72     int64_t max_written_offset = file_handle->GetMaxWrittenOffset();
73     ignore_result(file_handle.release());
74     return max_written_offset;
75   }
76   NOTREACHED();
77   return 0;
78 }
79 
CloseFile(int32_t id,const ppapi::FileGrowth & file_growth)80 void QuotaReservation::CloseFile(int32_t id,
81                                  const ppapi::FileGrowth& file_growth) {
82   FileMap::iterator it = files_.find(id);
83   if (it != files_.end()) {
84     it->second->UpdateMaxWrittenOffset(file_growth.max_written_offset);
85     it->second->AddAppendModeWriteAmount(file_growth.append_mode_write_amount);
86     delete it->second;
87     files_.erase(it);
88   } else {
89     NOTREACHED();
90   }
91 }
92 
ReserveQuota(int64_t amount,const ppapi::FileGrowthMap & file_growths,const ReserveQuotaCallback & callback)93 void QuotaReservation::ReserveQuota(int64_t amount,
94                                     const ppapi::FileGrowthMap& file_growths,
95                                     const ReserveQuotaCallback& callback) {
96   for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it) {
97     ppapi::FileGrowthMap::const_iterator growth_it =
98         file_growths.find(it->first);
99     if (growth_it != file_growths.end()) {
100       it->second->UpdateMaxWrittenOffset(growth_it->second.max_written_offset);
101       it->second->AddAppendModeWriteAmount(
102           growth_it->second.append_mode_write_amount);
103     } else {
104       NOTREACHED();
105     }
106   }
107 
108   quota_reservation_->RefreshReservation(
109       amount, base::Bind(&QuotaReservation::GotReservedQuota, this, callback));
110 }
111 
OnClientCrash()112 void QuotaReservation::OnClientCrash() { quota_reservation_->OnClientCrash(); }
113 
GotReservedQuota(const ReserveQuotaCallback & callback,base::File::Error error)114 void QuotaReservation::GotReservedQuota(const ReserveQuotaCallback& callback,
115                                         base::File::Error error) {
116   ppapi::FileSizeMap file_sizes;
117   for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it)
118     file_sizes[it->first] = it->second->GetMaxWrittenOffset();
119 
120   if (file_system_context_.get()) {
121     BrowserThread::PostTask(
122         BrowserThread::IO,
123         FROM_HERE,
124         base::Bind(
125             callback, quota_reservation_->remaining_quota(), file_sizes));
126   } else {
127     // Unit testing code path.
128     callback.Run(quota_reservation_->remaining_quota(), file_sizes);
129   }
130 }
131 
DeleteOnCorrectThread() const132 void QuotaReservation::DeleteOnCorrectThread() const {
133   if (file_system_context_.get() &&
134       !file_system_context_->default_file_task_runner()
135            ->RunsTasksOnCurrentThread()) {
136     file_system_context_->default_file_task_runner()->DeleteSoon(FROM_HERE,
137                                                                  this);
138   } else {
139     // We're on the right thread to delete, or unit test.
140     delete this;
141   }
142 }
143 
144 }  // namespace content
145