OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h" | 5 #include "storage/browser/fileapi/sandbox_file_stream_writer.h" |
6 | 6 |
7 #include "base/files/file_util_proxy.h" | 7 #include "base/files/file_util_proxy.h" |
8 #include "base/sequenced_task_runner.h" | 8 #include "base/sequenced_task_runner.h" |
9 #include "net/base/io_buffer.h" | 9 #include "net/base/io_buffer.h" |
10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
11 #include "webkit/browser/blob/file_stream_reader.h" | 11 #include "storage/browser/blob/file_stream_reader.h" |
12 #include "webkit/browser/fileapi/file_observers.h" | 12 #include "storage/browser/fileapi/file_observers.h" |
13 #include "webkit/browser/fileapi/file_stream_writer.h" | 13 #include "storage/browser/fileapi/file_stream_writer.h" |
14 #include "webkit/browser/fileapi/file_system_context.h" | 14 #include "storage/browser/fileapi/file_system_context.h" |
15 #include "webkit/browser/fileapi/file_system_operation_runner.h" | 15 #include "storage/browser/fileapi/file_system_operation_runner.h" |
16 #include "webkit/browser/quota/quota_manager_proxy.h" | 16 #include "storage/browser/quota/quota_manager_proxy.h" |
17 #include "webkit/common/fileapi/file_system_util.h" | 17 #include "storage/common/fileapi/file_system_util.h" |
18 | 18 |
19 namespace fileapi { | 19 namespace storage { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 // Adjust the |quota| value in overwriting case (i.e. |file_size| > 0 and | 23 // Adjust the |quota| value in overwriting case (i.e. |file_size| > 0 and |
24 // |file_offset| < |file_size|) to make the remaining quota calculation easier. | 24 // |file_offset| < |file_size|) to make the remaining quota calculation easier. |
25 // Specifically this widens the quota for overlapping range (so that we can | 25 // Specifically this widens the quota for overlapping range (so that we can |
26 // simply compare written bytes against the adjusted quota). | 26 // simply compare written bytes against the adjusted quota). |
27 int64 AdjustQuotaForOverlap(int64 quota, | 27 int64 AdjustQuotaForOverlap(int64 quota, int64 file_offset, int64 file_size) { |
28 int64 file_offset, | |
29 int64 file_size) { | |
30 DCHECK_LE(file_offset, file_size); | 28 DCHECK_LE(file_offset, file_size); |
31 if (quota < 0) | 29 if (quota < 0) |
32 quota = 0; | 30 quota = 0; |
33 int64 overlap = file_size - file_offset; | 31 int64 overlap = file_size - file_offset; |
34 if (kint64max - overlap > quota) | 32 if (kint64max - overlap > quota) |
35 quota += overlap; | 33 quota += overlap; |
36 return quota; | 34 return quota; |
37 } | 35 } |
38 | 36 |
39 } // namespace | 37 } // namespace |
40 | 38 |
41 SandboxFileStreamWriter::SandboxFileStreamWriter( | 39 SandboxFileStreamWriter::SandboxFileStreamWriter( |
42 FileSystemContext* file_system_context, | 40 FileSystemContext* file_system_context, |
43 const FileSystemURL& url, | 41 const FileSystemURL& url, |
44 int64 initial_offset, | 42 int64 initial_offset, |
45 const UpdateObserverList& observers) | 43 const UpdateObserverList& observers) |
46 : file_system_context_(file_system_context), | 44 : file_system_context_(file_system_context), |
47 url_(url), | 45 url_(url), |
48 initial_offset_(initial_offset), | 46 initial_offset_(initial_offset), |
49 observers_(observers), | 47 observers_(observers), |
50 file_size_(0), | 48 file_size_(0), |
51 total_bytes_written_(0), | 49 total_bytes_written_(0), |
52 allowed_bytes_to_write_(0), | 50 allowed_bytes_to_write_(0), |
53 has_pending_operation_(false), | 51 has_pending_operation_(false), |
54 default_quota_(kint64max), | 52 default_quota_(kint64max), |
55 weak_factory_(this) { | 53 weak_factory_(this) { |
56 DCHECK(url_.is_valid()); | 54 DCHECK(url_.is_valid()); |
57 } | 55 } |
58 | 56 |
59 SandboxFileStreamWriter::~SandboxFileStreamWriter() {} | 57 SandboxFileStreamWriter::~SandboxFileStreamWriter() { |
| 58 } |
60 | 59 |
61 int SandboxFileStreamWriter::Write( | 60 int SandboxFileStreamWriter::Write(net::IOBuffer* buf, |
62 net::IOBuffer* buf, int buf_len, | 61 int buf_len, |
63 const net::CompletionCallback& callback) { | 62 const net::CompletionCallback& callback) { |
64 has_pending_operation_ = true; | 63 has_pending_operation_ = true; |
65 if (local_file_writer_) | 64 if (local_file_writer_) |
66 return WriteInternal(buf, buf_len, callback); | 65 return WriteInternal(buf, buf_len, callback); |
67 | 66 |
68 net::CompletionCallback write_task = | 67 net::CompletionCallback write_task = |
69 base::Bind(&SandboxFileStreamWriter::DidInitializeForWrite, | 68 base::Bind(&SandboxFileStreamWriter::DidInitializeForWrite, |
70 weak_factory_.GetWeakPtr(), | 69 weak_factory_.GetWeakPtr(), |
71 make_scoped_refptr(buf), buf_len, callback); | 70 make_scoped_refptr(buf), |
| 71 buf_len, |
| 72 callback); |
72 file_system_context_->operation_runner()->CreateSnapshotFile( | 73 file_system_context_->operation_runner()->CreateSnapshotFile( |
73 url_, base::Bind(&SandboxFileStreamWriter::DidCreateSnapshotFile, | 74 url_, |
74 weak_factory_.GetWeakPtr(), write_task)); | 75 base::Bind(&SandboxFileStreamWriter::DidCreateSnapshotFile, |
| 76 weak_factory_.GetWeakPtr(), |
| 77 write_task)); |
75 return net::ERR_IO_PENDING; | 78 return net::ERR_IO_PENDING; |
76 } | 79 } |
77 | 80 |
78 int SandboxFileStreamWriter::Cancel(const net::CompletionCallback& callback) { | 81 int SandboxFileStreamWriter::Cancel(const net::CompletionCallback& callback) { |
79 if (!has_pending_operation_) | 82 if (!has_pending_operation_) |
80 return net::ERR_UNEXPECTED; | 83 return net::ERR_UNEXPECTED; |
81 | 84 |
82 DCHECK(!callback.is_null()); | 85 DCHECK(!callback.is_null()); |
83 cancel_callback_ = callback; | 86 cancel_callback_ = callback; |
84 return net::ERR_IO_PENDING; | 87 return net::ERR_IO_PENDING; |
85 } | 88 } |
86 | 89 |
87 int SandboxFileStreamWriter::WriteInternal( | 90 int SandboxFileStreamWriter::WriteInternal( |
88 net::IOBuffer* buf, int buf_len, | 91 net::IOBuffer* buf, |
| 92 int buf_len, |
89 const net::CompletionCallback& callback) { | 93 const net::CompletionCallback& callback) { |
90 // allowed_bytes_to_write could be negative if the file size is | 94 // allowed_bytes_to_write could be negative if the file size is |
91 // greater than the current (possibly new) quota. | 95 // greater than the current (possibly new) quota. |
92 DCHECK(total_bytes_written_ <= allowed_bytes_to_write_ || | 96 DCHECK(total_bytes_written_ <= allowed_bytes_to_write_ || |
93 allowed_bytes_to_write_ < 0); | 97 allowed_bytes_to_write_ < 0); |
94 if (total_bytes_written_ >= allowed_bytes_to_write_) { | 98 if (total_bytes_written_ >= allowed_bytes_to_write_) { |
95 has_pending_operation_ = false; | 99 has_pending_operation_ = false; |
96 return net::ERR_FILE_NO_SPACE; | 100 return net::ERR_FILE_NO_SPACE; |
97 } | 101 } |
98 | 102 |
99 if (buf_len > allowed_bytes_to_write_ - total_bytes_written_) | 103 if (buf_len > allowed_bytes_to_write_ - total_bytes_written_) |
100 buf_len = allowed_bytes_to_write_ - total_bytes_written_; | 104 buf_len = allowed_bytes_to_write_ - total_bytes_written_; |
101 | 105 |
102 DCHECK(local_file_writer_.get()); | 106 DCHECK(local_file_writer_.get()); |
103 const int result = local_file_writer_->Write( | 107 const int result = |
104 buf, buf_len, | 108 local_file_writer_->Write(buf, |
105 base::Bind(&SandboxFileStreamWriter::DidWrite, weak_factory_.GetWeakPtr(), | 109 buf_len, |
106 callback)); | 110 base::Bind(&SandboxFileStreamWriter::DidWrite, |
| 111 weak_factory_.GetWeakPtr(), |
| 112 callback)); |
107 if (result != net::ERR_IO_PENDING) | 113 if (result != net::ERR_IO_PENDING) |
108 has_pending_operation_ = false; | 114 has_pending_operation_ = false; |
109 return result; | 115 return result; |
110 } | 116 } |
111 | 117 |
112 void SandboxFileStreamWriter::DidCreateSnapshotFile( | 118 void SandboxFileStreamWriter::DidCreateSnapshotFile( |
113 const net::CompletionCallback& callback, | 119 const net::CompletionCallback& callback, |
114 base::File::Error file_error, | 120 base::File::Error file_error, |
115 const base::File::Info& file_info, | 121 const base::File::Info& file_info, |
116 const base::FilePath& platform_path, | 122 const base::FilePath& platform_path, |
117 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { | 123 const scoped_refptr<storage::ShareableFileReference>& file_ref) { |
118 DCHECK(!file_ref.get()); | 124 DCHECK(!file_ref.get()); |
119 | 125 |
120 if (CancelIfRequested()) | 126 if (CancelIfRequested()) |
121 return; | 127 return; |
122 if (file_error != base::File::FILE_OK) { | 128 if (file_error != base::File::FILE_OK) { |
123 callback.Run(net::FileErrorToNetError(file_error)); | 129 callback.Run(net::FileErrorToNetError(file_error)); |
124 return; | 130 return; |
125 } | 131 } |
126 if (file_info.is_directory) { | 132 if (file_info.is_directory) { |
127 // We should not be writing to a directory. | 133 // We should not be writing to a directory. |
(...skipping 22 matching lines...) Expand all Loading... |
150 allowed_bytes_to_write_ = default_quota_; | 156 allowed_bytes_to_write_ = default_quota_; |
151 callback.Run(net::OK); | 157 callback.Run(net::OK); |
152 return; | 158 return; |
153 } | 159 } |
154 | 160 |
155 DCHECK(quota_manager_proxy->quota_manager()); | 161 DCHECK(quota_manager_proxy->quota_manager()); |
156 quota_manager_proxy->quota_manager()->GetUsageAndQuota( | 162 quota_manager_proxy->quota_manager()->GetUsageAndQuota( |
157 url_.origin(), | 163 url_.origin(), |
158 FileSystemTypeToQuotaStorageType(url_.type()), | 164 FileSystemTypeToQuotaStorageType(url_.type()), |
159 base::Bind(&SandboxFileStreamWriter::DidGetUsageAndQuota, | 165 base::Bind(&SandboxFileStreamWriter::DidGetUsageAndQuota, |
160 weak_factory_.GetWeakPtr(), callback)); | 166 weak_factory_.GetWeakPtr(), |
| 167 callback)); |
161 } | 168 } |
162 | 169 |
163 void SandboxFileStreamWriter::DidGetUsageAndQuota( | 170 void SandboxFileStreamWriter::DidGetUsageAndQuota( |
164 const net::CompletionCallback& callback, | 171 const net::CompletionCallback& callback, |
165 quota::QuotaStatusCode status, | 172 quota::QuotaStatusCode status, |
166 int64 usage, int64 quota) { | 173 int64 usage, |
| 174 int64 quota) { |
167 if (CancelIfRequested()) | 175 if (CancelIfRequested()) |
168 return; | 176 return; |
169 if (status != quota::kQuotaStatusOk) { | 177 if (status != quota::kQuotaStatusOk) { |
170 LOG(WARNING) << "Got unexpected quota error : " << status; | 178 LOG(WARNING) << "Got unexpected quota error : " << status; |
171 callback.Run(net::ERR_FAILED); | 179 callback.Run(net::ERR_FAILED); |
172 return; | 180 return; |
173 } | 181 } |
174 | 182 |
175 allowed_bytes_to_write_ = quota - usage; | 183 allowed_bytes_to_write_ = quota - usage; |
176 callback.Run(net::OK); | 184 callback.Run(net::OK); |
177 } | 185 } |
178 | 186 |
179 void SandboxFileStreamWriter::DidInitializeForWrite( | 187 void SandboxFileStreamWriter::DidInitializeForWrite( |
180 net::IOBuffer* buf, int buf_len, | 188 net::IOBuffer* buf, |
| 189 int buf_len, |
181 const net::CompletionCallback& callback, | 190 const net::CompletionCallback& callback, |
182 int init_status) { | 191 int init_status) { |
183 if (CancelIfRequested()) | 192 if (CancelIfRequested()) |
184 return; | 193 return; |
185 if (init_status != net::OK) { | 194 if (init_status != net::OK) { |
186 has_pending_operation_ = false; | 195 has_pending_operation_ = false; |
187 callback.Run(init_status); | 196 callback.Run(init_status); |
188 return; | 197 return; |
189 } | 198 } |
190 allowed_bytes_to_write_ = AdjustQuotaForOverlap( | 199 allowed_bytes_to_write_ = AdjustQuotaForOverlap( |
191 allowed_bytes_to_write_, initial_offset_, file_size_); | 200 allowed_bytes_to_write_, initial_offset_, file_size_); |
192 const int result = WriteInternal(buf, buf_len, callback); | 201 const int result = WriteInternal(buf, buf_len, callback); |
193 if (result != net::ERR_IO_PENDING) | 202 if (result != net::ERR_IO_PENDING) |
194 callback.Run(result); | 203 callback.Run(result); |
195 } | 204 } |
196 | 205 |
197 void SandboxFileStreamWriter::DidWrite( | 206 void SandboxFileStreamWriter::DidWrite(const net::CompletionCallback& callback, |
198 const net::CompletionCallback& callback, | 207 int write_response) { |
199 int write_response) { | |
200 DCHECK(has_pending_operation_); | 208 DCHECK(has_pending_operation_); |
201 has_pending_operation_ = false; | 209 has_pending_operation_ = false; |
202 | 210 |
203 if (write_response <= 0) { | 211 if (write_response <= 0) { |
204 if (CancelIfRequested()) | 212 if (CancelIfRequested()) |
205 return; | 213 return; |
206 callback.Run(write_response); | 214 callback.Run(write_response); |
207 return; | 215 return; |
208 } | 216 } |
209 | 217 |
(...skipping 26 matching lines...) Expand all Loading... |
236 DCHECK(!has_pending_operation_); | 244 DCHECK(!has_pending_operation_); |
237 DCHECK(cancel_callback_.is_null()); | 245 DCHECK(cancel_callback_.is_null()); |
238 | 246 |
239 // Write() is not called yet, so there's nothing to flush. | 247 // Write() is not called yet, so there's nothing to flush. |
240 if (!local_file_writer_) | 248 if (!local_file_writer_) |
241 return net::OK; | 249 return net::OK; |
242 | 250 |
243 return local_file_writer_->Flush(callback); | 251 return local_file_writer_->Flush(callback); |
244 } | 252 } |
245 | 253 |
246 } // namespace fileapi | 254 } // namespace storage |
OLD | NEW |