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

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

Issue 10008047: FileWriterDelegate should not call URLRequest::Start() after Cancel(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: reverted the test 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/file_writer_delegate.h ('k') | webkit/fileapi/file_writer_delegate_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/fileapi/file_writer_delegate.h" 5 #include "webkit/fileapi/file_writer_delegate.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/file_util_proxy.h" 9 #include "base/file_util_proxy.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 14 matching lines...) Expand all
25 namespace { 25 namespace {
26 26
27 typedef base::Callback<void(base::PlatformFileError /* error code */, 27 typedef base::Callback<void(base::PlatformFileError /* error code */,
28 const base::PlatformFileInfo& /* file_info */)> 28 const base::PlatformFileInfo& /* file_info */)>
29 InitializeTaskCallback; 29 InitializeTaskCallback;
30 30
31 class InitializeTask : public base::RefCountedThreadSafe<InitializeTask> { 31 class InitializeTask : public base::RefCountedThreadSafe<InitializeTask> {
32 public: 32 public:
33 InitializeTask( 33 InitializeTask(
34 base::PlatformFile file, 34 base::PlatformFile file,
35 const FileSystemPath& path,
36 FileSystemOperationContext* context,
37 const InitializeTaskCallback& callback) 35 const InitializeTaskCallback& callback)
38 : original_loop_(base::MessageLoopProxy::current()), 36 : original_loop_(base::MessageLoopProxy::current()),
39 error_code_(base::PLATFORM_FILE_OK), 37 error_code_(base::PLATFORM_FILE_OK),
40 file_(file), 38 file_(file),
41 path_(path),
42 context_(*context),
43 callback_(callback) { 39 callback_(callback) {
44 DCHECK_EQ(false, callback.is_null()); 40 DCHECK_EQ(false, callback.is_null());
45 } 41 }
46 42
47 bool Start(base::SequencedTaskRunner* task_runner, 43 bool Start(base::SequencedTaskRunner* task_runner,
48 const tracked_objects::Location& from_here) { 44 const tracked_objects::Location& from_here) {
49 return task_runner->PostTask( 45 return task_runner->PostTask(
50 from_here, 46 from_here,
51 base::Bind(&InitializeTask::ProcessOnTargetThread, this)); 47 base::Bind(&InitializeTask::ProcessOnTargetThread, this));
52 } 48 }
53 49
54 private: 50 private:
55 friend class base::RefCountedThreadSafe<InitializeTask>; 51 friend class base::RefCountedThreadSafe<InitializeTask>;
56 ~InitializeTask() {} 52 ~InitializeTask() {}
57 53
58 void RunCallback() { 54 void RunCallback() {
59 callback_.Run(error_code_, file_info_); 55 callback_.Run(error_code_, file_info_);
60 } 56 }
61 57
62 void ProcessOnTargetThread() { 58 void ProcessOnTargetThread() {
63 DCHECK(context_.file_system_context());
64 FileSystemQuotaUtil* quota_util = context_.file_system_context()->
65 GetQuotaUtil(path_.type());
66 if (quota_util) {
67 DCHECK(quota_util->proxy());
68 quota_util->proxy()->StartUpdateOrigin(path_.origin(), path_.type());
69 }
70 if (!base::GetPlatformFileInfo(file_, &file_info_)) 59 if (!base::GetPlatformFileInfo(file_, &file_info_))
71 error_code_ = base::PLATFORM_FILE_ERROR_FAILED; 60 error_code_ = base::PLATFORM_FILE_ERROR_FAILED;
72 original_loop_->PostTask( 61 original_loop_->PostTask(
73 FROM_HERE, 62 FROM_HERE,
74 base::Bind(&InitializeTask::RunCallback, this)); 63 base::Bind(&InitializeTask::RunCallback, this));
75 } 64 }
76 65
77 scoped_refptr<base::MessageLoopProxy> original_loop_; 66 scoped_refptr<base::MessageLoopProxy> original_loop_;
78 base::PlatformFileError error_code_; 67 base::PlatformFileError error_code_;
79 68
80 base::PlatformFile file_; 69 base::PlatformFile file_;
81 FileSystemPath path_;
82 FileSystemOperationContext context_;
83 InitializeTaskCallback callback_; 70 InitializeTaskCallback callback_;
84 71
85 base::PlatformFileInfo file_info_; 72 base::PlatformFileInfo file_info_;
86 }; 73 };
87 74
88 } // namespace (anonymous) 75 } // namespace (anonymous)
89 76
90 FileWriterDelegate::FileWriterDelegate( 77 FileWriterDelegate::FileWriterDelegate(
91 FileSystemOperation* file_system_operation, 78 FileSystemOperation* file_system_operation,
92 const FileSystemPath& path, 79 const FileSystemPath& path,
93 int64 offset) 80 int64 offset)
94 : file_system_operation_(file_system_operation), 81 : file_system_operation_(file_system_operation),
95 file_(base::kInvalidPlatformFileValue), 82 file_(base::kInvalidPlatformFileValue),
96 path_(path), 83 path_(path),
97 offset_(offset), 84 offset_(offset),
85 has_pending_write_(false),
98 bytes_written_backlog_(0), 86 bytes_written_backlog_(0),
99 bytes_written_(0), 87 bytes_written_(0),
100 bytes_read_(0), 88 bytes_read_(0),
101 total_bytes_written_(0), 89 total_bytes_written_(0),
102 allowed_bytes_to_write_(0), 90 allowed_bytes_to_write_(0),
103 io_buffer_(new net::IOBufferWithSize(kReadBufSize)), 91 io_buffer_(new net::IOBufferWithSize(kReadBufSize)),
104 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { 92 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
105 } 93 }
106 94
107 FileWriterDelegate::~FileWriterDelegate() { 95 FileWriterDelegate::~FileWriterDelegate() {
108 } 96 }
109 97
110 void FileWriterDelegate::OnGetFileInfoAndCallStartUpdate( 98 void FileWriterDelegate::OnGetFileInfoAndStartRequest(
99 scoped_ptr<net::URLRequest> request,
111 base::PlatformFileError error, 100 base::PlatformFileError error,
112 const base::PlatformFileInfo& file_info) { 101 const base::PlatformFileInfo& file_info) {
113 if (error) { 102 if (error != base::PLATFORM_FILE_OK) {
114 OnError(error); 103 OnError(error);
115 return; 104 return;
116 } 105 }
117 int64 allowed_bytes_growth = 106 int64 allowed_bytes_growth =
118 file_system_operation_context()->allowed_bytes_growth(); 107 file_system_operation_context()->allowed_bytes_growth();
119 if (allowed_bytes_growth < 0) 108 if (allowed_bytes_growth < 0)
120 allowed_bytes_growth = 0; 109 allowed_bytes_growth = 0;
121 int64 overlap = file_info.size - offset_; 110 int64 overlap = file_info.size - offset_;
122 allowed_bytes_to_write_ = allowed_bytes_growth; 111 allowed_bytes_to_write_ = allowed_bytes_growth;
123 if (kint64max - overlap > allowed_bytes_growth) 112 if (kint64max - overlap > allowed_bytes_growth)
124 allowed_bytes_to_write_ += overlap; 113 allowed_bytes_to_write_ += overlap;
125 size_ = file_info.size; 114 size_ = file_info.size;
126 file_stream_.reset(new net::FileStream( 115 file_stream_.reset(new net::FileStream(
127 file_, 116 file_,
128 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE | 117 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE |
129 base::PLATFORM_FILE_ASYNC, 118 base::PLATFORM_FILE_ASYNC,
130 NULL)); 119 NULL));
120 DCHECK(!request_.get());
121 request_ = request.Pass();
131 request_->Start(); 122 request_->Start();
132 } 123 }
133 124
134 void FileWriterDelegate::Start(base::PlatformFile file, 125 void FileWriterDelegate::Start(base::PlatformFile file,
135 net::URLRequest* request) { 126 scoped_ptr<net::URLRequest> request) {
136 file_ = file; 127 file_ = file;
137 request_ = request;
138 128
139 scoped_refptr<InitializeTask> relay = new InitializeTask( 129 scoped_refptr<InitializeTask> relay = new InitializeTask(
140 file_, path_, 130 file_,
141 file_system_operation_context(), 131 base::Bind(&FileWriterDelegate::OnGetFileInfoAndStartRequest,
142 base::Bind(&FileWriterDelegate::OnGetFileInfoAndCallStartUpdate, 132 weak_factory_.GetWeakPtr(), base::Passed(&request)));
143 weak_factory_.GetWeakPtr()));
144 relay->Start(file_system_operation_context()->file_task_runner(), FROM_HERE); 133 relay->Start(file_system_operation_context()->file_task_runner(), FROM_HERE);
145 } 134 }
146 135
136 bool FileWriterDelegate::Cancel() {
137 if (request_.get()) {
138 // This halts any callbacks on this delegate.
139 request_->set_delegate(NULL);
140 request_->Cancel();
141 }
142
143 // Return true to finish immediately if we're not writing.
144 // Otherwise we'll do the final cleanup in the write callback.
145 return !has_pending_write_;
146 }
147
147 void FileWriterDelegate::OnReceivedRedirect(net::URLRequest* request, 148 void FileWriterDelegate::OnReceivedRedirect(net::URLRequest* request,
148 const GURL& new_url, 149 const GURL& new_url,
149 bool* defer_redirect) { 150 bool* defer_redirect) {
150 NOTREACHED(); 151 NOTREACHED();
151 OnError(base::PLATFORM_FILE_ERROR_SECURITY); 152 OnError(base::PLATFORM_FILE_ERROR_SECURITY);
152 } 153 }
153 154
154 void FileWriterDelegate::OnAuthRequired(net::URLRequest* request, 155 void FileWriterDelegate::OnAuthRequired(net::URLRequest* request,
155 net::AuthChallengeInfo* auth_info) { 156 net::AuthChallengeInfo* auth_info) {
156 NOTREACHED(); 157 NOTREACHED();
157 OnError(base::PLATFORM_FILE_ERROR_SECURITY); 158 OnError(base::PLATFORM_FILE_ERROR_SECURITY);
158 } 159 }
159 160
160 void FileWriterDelegate::OnCertificateRequested( 161 void FileWriterDelegate::OnCertificateRequested(
161 net::URLRequest* request, 162 net::URLRequest* request,
162 net::SSLCertRequestInfo* cert_request_info) { 163 net::SSLCertRequestInfo* cert_request_info) {
163 NOTREACHED(); 164 NOTREACHED();
164 OnError(base::PLATFORM_FILE_ERROR_SECURITY); 165 OnError(base::PLATFORM_FILE_ERROR_SECURITY);
165 } 166 }
166 167
167 void FileWriterDelegate::OnSSLCertificateError(net::URLRequest* request, 168 void FileWriterDelegate::OnSSLCertificateError(net::URLRequest* request,
168 const net::SSLInfo& ssl_info, 169 const net::SSLInfo& ssl_info,
169 bool fatal) { 170 bool fatal) {
170 NOTREACHED(); 171 NOTREACHED();
171 OnError(base::PLATFORM_FILE_ERROR_SECURITY); 172 OnError(base::PLATFORM_FILE_ERROR_SECURITY);
172 } 173 }
173 174
174 void FileWriterDelegate::OnResponseStarted(net::URLRequest* request) { 175 void FileWriterDelegate::OnResponseStarted(net::URLRequest* request) {
175 DCHECK_EQ(request_, request); 176 DCHECK_EQ(request_.get(), request);
176 // file_stream_->Seek() blocks the IO thread. 177 // file_stream_->Seek() blocks the IO thread.
177 // See http://crbug.com/75548. 178 // See http://crbug.com/75548.
178 base::ThreadRestrictions::ScopedAllowIO allow_io; 179 base::ThreadRestrictions::ScopedAllowIO allow_io;
179 if (!request->status().is_success() || request->GetResponseCode() != 200) { 180 if (!request->status().is_success() || request->GetResponseCode() != 200) {
180 OnError(base::PLATFORM_FILE_ERROR_FAILED); 181 OnError(base::PLATFORM_FILE_ERROR_FAILED);
181 return; 182 return;
182 } 183 }
183 int64 error = file_stream_->SeekSync(net::FROM_BEGIN, offset_); 184 int64 error = file_stream_->SeekSync(net::FROM_BEGIN, offset_);
184 if (error != offset_) { 185 if (error != offset_) {
185 OnError(base::PLATFORM_FILE_ERROR_FAILED); 186 OnError(base::PLATFORM_FILE_ERROR_FAILED);
186 return; 187 return;
187 } 188 }
188 Read(); 189 Read();
189 } 190 }
190 191
191 void FileWriterDelegate::OnReadCompleted(net::URLRequest* request, 192 void FileWriterDelegate::OnReadCompleted(net::URLRequest* request,
192 int bytes_read) { 193 int bytes_read) {
193 DCHECK_EQ(request_, request); 194 DCHECK_EQ(request_.get(), request);
194 if (!request->status().is_success()) { 195 if (!request->status().is_success()) {
195 OnError(base::PLATFORM_FILE_ERROR_FAILED); 196 OnError(base::PLATFORM_FILE_ERROR_FAILED);
196 return; 197 return;
197 } 198 }
198 OnDataReceived(bytes_read); 199 OnDataReceived(bytes_read);
199 } 200 }
200 201
201 void FileWriterDelegate::Read() { 202 void FileWriterDelegate::Read() {
202 bytes_written_ = 0; 203 bytes_written_ = 0;
203 bytes_read_ = 0; 204 bytes_read_ = 0;
(...skipping 30 matching lines...) Expand all
234 allowed_bytes_to_write_ < 0); 235 allowed_bytes_to_write_ < 0);
235 if (total_bytes_written_ >= allowed_bytes_to_write_) { 236 if (total_bytes_written_ >= allowed_bytes_to_write_) {
236 OnError(base::PLATFORM_FILE_ERROR_NO_SPACE); 237 OnError(base::PLATFORM_FILE_ERROR_NO_SPACE);
237 return; 238 return;
238 } 239 }
239 240
240 int64 bytes_to_write = bytes_read_ - bytes_written_; 241 int64 bytes_to_write = bytes_read_ - bytes_written_;
241 if (bytes_to_write > allowed_bytes_to_write_ - total_bytes_written_) 242 if (bytes_to_write > allowed_bytes_to_write_ - total_bytes_written_)
242 bytes_to_write = allowed_bytes_to_write_ - total_bytes_written_; 243 bytes_to_write = allowed_bytes_to_write_ - total_bytes_written_;
243 244
245 has_pending_write_ = true;
244 int write_response = 246 int write_response =
245 file_stream_->Write(cursor_, 247 file_stream_->Write(cursor_,
246 static_cast<int>(bytes_to_write), 248 static_cast<int>(bytes_to_write),
247 base::Bind(&FileWriterDelegate::OnDataWritten, 249 base::Bind(&FileWriterDelegate::OnDataWritten,
248 weak_factory_.GetWeakPtr())); 250 weak_factory_.GetWeakPtr()));
249 if (write_response > 0) 251 if (write_response > 0)
250 MessageLoop::current()->PostTask( 252 MessageLoop::current()->PostTask(
251 FROM_HERE, 253 FROM_HERE,
252 base::Bind(&FileWriterDelegate::OnDataWritten, 254 base::Bind(&FileWriterDelegate::OnDataWritten,
253 weak_factory_.GetWeakPtr(), write_response)); 255 weak_factory_.GetWeakPtr(), write_response));
254 else if (net::ERR_IO_PENDING != write_response) 256 else if (net::ERR_IO_PENDING != write_response)
255 OnError(base::PLATFORM_FILE_ERROR_FAILED); 257 OnError(base::PLATFORM_FILE_ERROR_FAILED);
256 } 258 }
257 259
258 void FileWriterDelegate::OnDataWritten(int write_response) { 260 void FileWriterDelegate::OnDataWritten(int write_response) {
261 has_pending_write_ = false;
259 if (write_response > 0) { 262 if (write_response > 0) {
263 if (request_->status().status() == net::URLRequestStatus::CANCELED) {
264 OnProgress(write_response, true);
265 return;
266 }
260 OnProgress(write_response, false); 267 OnProgress(write_response, false);
261 cursor_->DidConsume(write_response); 268 cursor_->DidConsume(write_response);
262 bytes_written_ += write_response; 269 bytes_written_ += write_response;
263 total_bytes_written_ += write_response; 270 total_bytes_written_ += write_response;
264 if (bytes_written_ == bytes_read_) 271 if (bytes_written_ == bytes_read_)
265 Read(); 272 Read();
266 else 273 else
267 Write(); 274 Write();
268 } else { 275 } else {
269 OnError(base::PLATFORM_FILE_ERROR_FAILED); 276 OnError(base::PLATFORM_FILE_ERROR_FAILED);
270 } 277 }
271 } 278 }
272 279
273 void FileWriterDelegate::OnError(base::PlatformFileError error) { 280 void FileWriterDelegate::OnError(base::PlatformFileError error) {
274 request_->set_delegate(NULL); 281 if (request_.get()) {
275 request_->Cancel(); 282 request_->set_delegate(NULL);
276 283 request_->Cancel();
277 if (quota_util()) 284 }
278 quota_util()->proxy()->EndUpdateOrigin(path_.origin(), path_.type());
279 285
280 file_system_operation_->DidWrite(error, 0, true); 286 file_system_operation_->DidWrite(error, 0, true);
281 } 287 }
282 288
283 void FileWriterDelegate::OnProgress(int bytes_written, bool done) { 289 void FileWriterDelegate::OnProgress(int bytes_written, bool done) {
284 DCHECK(bytes_written + bytes_written_backlog_ >= bytes_written_backlog_); 290 DCHECK(bytes_written + bytes_written_backlog_ >= bytes_written_backlog_);
285 if (quota_util() && 291 if (quota_util() &&
286 bytes_written > 0 && 292 bytes_written > 0 &&
287 total_bytes_written_ + bytes_written + offset_ > size_) { 293 total_bytes_written_ + bytes_written + offset_ > size_) {
288 int overlapped = 0; 294 int overlapped = 0;
(...skipping 30 matching lines...) Expand all
319 325
320 FileSystemQuotaUtil* FileWriterDelegate::quota_util() const { 326 FileSystemQuotaUtil* FileWriterDelegate::quota_util() const {
321 DCHECK(file_system_operation_); 327 DCHECK(file_system_operation_);
322 DCHECK(file_system_operation_->file_system_context()); 328 DCHECK(file_system_operation_->file_system_context());
323 DCHECK(file_system_operation_->file_system_operation_context()); 329 DCHECK(file_system_operation_->file_system_operation_context());
324 return file_system_operation_->file_system_context()->GetQuotaUtil( 330 return file_system_operation_->file_system_context()->GetQuotaUtil(
325 path_.type()); 331 path_.type());
326 } 332 }
327 333
328 } // namespace fileapi 334 } // namespace fileapi
OLDNEW
« no previous file with comments | « webkit/fileapi/file_writer_delegate.h ('k') | webkit/fileapi/file_writer_delegate_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698