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

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

Issue 10387054: Implement SandboxFileWriter and rewrite FileWriterDelegate to use it (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: /w Cancel Created 8 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
« no previous file with comments | « webkit/fileapi/sandbox_file_writer.h ('k') | webkit/fileapi/webkit_fileapi.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_file_writer.h"
6
7 #include "base/file_util_proxy.h"
8 #include "base/platform_file.h"
9 #include "base/sequenced_task_runner.h"
10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h"
12 #include "webkit/blob/local_file_reader.h"
13 #include "webkit/fileapi/file_system_context.h"
14 #include "webkit/fileapi/file_system_operation_interface.h"
15 #include "webkit/fileapi/file_system_quota_util.h"
16 #include "webkit/fileapi/file_system_util.h"
17 #include "webkit/fileapi/local_file_writer.h"
18 #include "webkit/quota/quota_manager.h"
19
20 namespace fileapi {
21
22 namespace {
23
24 int PlatformFileErrorToNetError(base::PlatformFileError error) {
25 // TODO(kinuko): Move this static method to more convenient place.
26 return webkit_blob::LocalFileReader::PlatformFileErrorToNetError(error);
27 }
28
29 // Adjust the |quota| value with given |file_offset| and |file_size| and
30 // return the new quota value.
31 int64 AdjustQuotaWithFileRange(int64 quota,
32 int64 file_offset,
33 int64 file_size) {
kinaba 2012/05/15 07:40:04 Not at all related to the intent of the current CL
kinuko 2012/05/15 11:20:37 Good point, done.
34 if (quota < 0)
35 quota = 0;
36 int64 overlap = file_size - file_offset;
37 if (kint64max - overlap > quota)
38 quota += overlap;
39 return quota;
40 }
41
42 } // namespace
43
44 SandboxFileWriter::SandboxFileWriter(
45 FileSystemContext* file_system_context,
46 const GURL& url,
47 int64 initial_offset)
48 : file_system_context_(file_system_context),
49 url_(url),
50 initial_offset_(initial_offset),
51 file_size_(0),
52 total_bytes_written_(0),
53 allowed_bytes_to_write_(0),
54 has_pending_operation_(false),
55 default_quota_(kint64max),
56 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
57 const bool result = CrackFileSystemURL(
58 url_, &origin_, &file_system_type_, &virtual_path_);
59 DCHECK(result);
60 }
61
62 SandboxFileWriter::~SandboxFileWriter() {
63 if (quota_util())
64 quota_util()->proxy()->EndUpdateOrigin(origin_, file_system_type_);
65 }
66
67 int SandboxFileWriter::Write(
68 net::IOBuffer* buf, int buf_len,
69 const net::CompletionCallback& callback) {
70 has_pending_operation_ = true;
71 if (local_file_writer_.get())
72 return WriteInternal(buf, buf_len, callback);
73
74 FileSystemOperationInterface* operation =
75 file_system_context_->CreateFileSystemOperation(url_);
76 DCHECK(operation);
77 net::CompletionCallback write_task =
78 base::Bind(&SandboxFileWriter::DidInitializeForWrite,
79 weak_factory_.GetWeakPtr(),
80 make_scoped_refptr(buf), buf_len, callback);
81 operation->GetMetadata(
82 url_, base::Bind(&SandboxFileWriter::DidGetFileInfo,
83 weak_factory_.GetWeakPtr(), write_task));
84 return net::ERR_IO_PENDING;
85 }
86
87 int SandboxFileWriter::Cancel(const net::CompletionCallback& callback) {
88 if (!has_pending_operation_)
89 return net::ERR_UNEXPECTED;
90
91 DCHECK(local_file_writer_.get());
92 DCHECK(!callback.is_null());
93 cancel_callback_ = callback;
94 return net::ERR_IO_PENDING;
95 }
96
97 int SandboxFileWriter::WriteInternal(
98 net::IOBuffer* buf, int buf_len,
99 const net::CompletionCallback& callback) {
100 // allowed_bytes_to_write could be negative if the file size is
101 // greater than the current (possibly new) quota.
102 DCHECK(total_bytes_written_ <= allowed_bytes_to_write_ ||
103 allowed_bytes_to_write_ < 0);
104 if (total_bytes_written_ >= allowed_bytes_to_write_) {
105 has_pending_operation_ = false;
106 return net::ERR_FILE_NO_SPACE;
107 }
108
109 if (buf_len > allowed_bytes_to_write_ - total_bytes_written_)
110 buf_len = allowed_bytes_to_write_ - total_bytes_written_;
111
112 DCHECK(local_file_writer_.get());
113 const int result = local_file_writer_->Write(
114 buf, buf_len,
115 base::Bind(&SandboxFileWriter::DidWrite, weak_factory_.GetWeakPtr(),
116 callback));
117 if (result != net::ERR_IO_PENDING)
118 has_pending_operation_ = false;
119 return result;
120 }
121
122 void SandboxFileWriter::DidGetFileInfo(
123 const net::CompletionCallback& callback,
124 base::PlatformFileError file_error,
125 const base::PlatformFileInfo& file_info,
126 const FilePath& platform_path) {
127 if (CancelIfRequested())
128 return;
129 if (file_error != base::PLATFORM_FILE_OK) {
130 callback.Run(PlatformFileErrorToNetError(file_error));
131 return;
132 }
133 if (file_info.is_directory) {
134 // We should not be writing to a directory.
135 callback.Run(net::ERR_ACCESS_DENIED);
136 return;
137 }
138 file_size_ = file_info.size;
139 DCHECK(!local_file_writer_.get());
140 local_file_writer_.reset(new LocalFileWriter(platform_path, initial_offset_));
141
142 quota::QuotaManagerProxy* quota_manager_proxy =
143 file_system_context_->quota_manager_proxy();
144 if (!quota_manager_proxy || !quota_util()) {
145 // If we don't have the quota manager or the requested filesystem type
146 // does not support quota, we should be able to let it go.
147 allowed_bytes_to_write_ = default_quota_;
148 callback.Run(net::OK);
149 return;
150 }
151
152 quota_util()->proxy()->StartUpdateOrigin(origin_, file_system_type_);
153 DCHECK(quota_manager_proxy->quota_manager());
154 quota_manager_proxy->quota_manager()->GetUsageAndQuota(
155 origin_,
156 FileSystemTypeToQuotaStorageType(file_system_type_),
157 base::Bind(&SandboxFileWriter::DidGetUsageAndQuota,
158 weak_factory_.GetWeakPtr(), callback));
159 }
160
161 void SandboxFileWriter::DidGetUsageAndQuota(
162 const net::CompletionCallback& callback,
163 quota::QuotaStatusCode status,
164 int64 usage, int64 quota) {
165 if (status != quota::kQuotaStatusOk) {
166 LOG(WARNING) << "Got unexpected quota error : " << status;
167 callback.Run(net::ERR_FAILED);
168 return;
169 }
170
171 allowed_bytes_to_write_ = quota - usage;
172 callback.Run(net::OK);
173 }
174
175 void SandboxFileWriter::DidInitializeForWrite(
176 net::IOBuffer* buf, int buf_len,
177 const net::CompletionCallback& callback,
178 int init_status) {
179 if (init_status != net::OK) {
180 has_pending_operation_ = false;
181 callback.Run(init_status);
182 return;
183 }
184 allowed_bytes_to_write_ = AdjustQuotaWithFileRange(
185 allowed_bytes_to_write_, initial_offset_, file_size_);
186 const int result = WriteInternal(buf, buf_len, callback);
187 if (result != net::ERR_IO_PENDING)
188 callback.Run(result);
189 }
190
191 void SandboxFileWriter::DidWrite(
192 const net::CompletionCallback& callback,
193 int write_response) {
194 DCHECK(has_pending_operation_);
195 has_pending_operation_ = false;
196
197 if (write_response <= 0) {
198 if (CancelIfRequested())
199 return;
200 callback.Run(write_response);
201 return;
202 }
203
204 if (quota_util() &&
205 total_bytes_written_ + write_response + initial_offset_ > file_size_) {
206 int overlapped = file_size_ - total_bytes_written_ - initial_offset_;
207 if (overlapped < 0)
208 overlapped = 0;
209 quota_util()->proxy()->UpdateOriginUsage(
210 file_system_context_->quota_manager_proxy(),
211 origin_, file_system_type_, write_response - overlapped);
212 }
213 total_bytes_written_ += write_response;
214
215 if (CancelIfRequested())
216 return;
217 callback.Run(write_response);
218 }
219
220 bool SandboxFileWriter::CancelIfRequested() {
221 if (cancel_callback_.is_null())
222 return false;
223
224 net::CompletionCallback pending_cancel = cancel_callback_;
225 has_pending_operation_ = false;
226 cancel_callback_.Reset();
227 pending_cancel.Run(net::OK);
228 return true;
229 }
230
231 FileSystemQuotaUtil* SandboxFileWriter::quota_util() const {
232 DCHECK(file_system_context_.get());
233 return file_system_context_->GetQuotaUtil(file_system_type_);
234 }
235
236 } // namespace fileapi
OLDNEW
« no previous file with comments | « webkit/fileapi/sandbox_file_writer.h ('k') | webkit/fileapi/webkit_fileapi.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698