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

Side by Side Diff: webkit/plugins/ppapi/quota_file_io.cc

Issue 7508010: Pepper quota fix: fire callbacks asynchronously to avoid crash in write callback chain (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 9 years, 4 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 | « no previous file | no next file » | 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/plugins/ppapi/quota_file_io.h" 5 #include "webkit/plugins/ppapi/quota_file_io.h"
6 6
7 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "base/message_loop_proxy.h" 8 #include "base/message_loop_proxy.h"
9 #include "base/task.h" 9 #include "base/task.h"
10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" 10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 if (!base::FileUtilProxy::Write( 93 if (!base::FileUtilProxy::Write(
94 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), 94 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(),
95 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, 95 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_,
96 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { 96 callback_factory_.NewCallback(&WriteOperation::DidFinish))) {
97 DidFail(base::PLATFORM_FILE_ERROR_FAILED); 97 DidFail(base::PLATFORM_FILE_ERROR_FAILED);
98 return; 98 return;
99 } 99 }
100 } 100 }
101 101
102 virtual void DidFail(PlatformFileError error) OVERRIDE { 102 virtual void DidFail(PlatformFileError error) OVERRIDE {
103 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( 103 base::MessageLoopProxy::CreateForCurrentThread()->PostTask(
yzshen1 2011/08/04 20:27:38 Would you please explain why this needs to be a po
kinuko 2011/08/05 18:29:56 The reason for these added post-tasks is: Run() is
yzshen1 2011/08/05 20:31:46 Thanks for explaining. On 2011/08/05 18:29:56, ki
104 FROM_HERE, runnable_factory_.NewRunnableMethod( 104 FROM_HERE, runnable_factory_.NewRunnableMethod(
105 &WriteOperation::DidFinish, error, 0)); 105 &WriteOperation::DidFinish, error, 0));
106 } 106 }
107 107
108 bool finished() const { return finished_; } 108 bool finished() const { return finished_; }
109 109
110 void RunCallbackSoon() {
111 base::MessageLoopProxy::CreateForCurrentThread()->PostTask(
112 FROM_HERE, runnable_factory_.NewRunnableMethod(
113 &WriteOperation::RunCallback));
114 }
115
116 private:
110 void RunCallback() { 117 void RunCallback() {
111 DCHECK(callback_.get()); 118 DCHECK(callback_.get());
112 callback_->Run(status_, bytes_written_); 119 callback_->Run(status_, bytes_written_);
113 callback_.reset(); 120 callback_.reset();
114 delete this; 121 delete this;
115 } 122 }
116 123
117 private:
118 void DidFinish(PlatformFileError status, int bytes_written) { 124 void DidFinish(PlatformFileError status, int bytes_written) {
119 finished_ = true; 125 finished_ = true;
120 status_ = status; 126 status_ = status;
121 bytes_written_ = bytes_written; 127 bytes_written_ = bytes_written;
122 int64_t max_offset = 128 int64_t max_offset =
123 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; 129 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written;
124 // This may delete itself by calling RunCallback. 130 // This may delete itself by calling RunCallback.
125 quota_io_->DidWrite(this, max_offset); 131 quota_io_->DidWrite(this, max_offset);
126 } 132 }
127 133
128 const int64_t offset_; 134 const int64_t offset_;
129 scoped_array<char> buffer_; 135 scoped_array<char> buffer_;
130 const int32_t bytes_to_write_; 136 const int32_t bytes_to_write_;
131 scoped_ptr<WriteCallback> callback_; 137 scoped_ptr<WriteCallback> callback_;
132 bool finished_; 138 bool finished_;
133 PlatformFileError status_; 139 PlatformFileError status_;
134 int64_t bytes_written_; 140 int64_t bytes_written_;
135 base::ScopedCallbackFactory<QuotaFileIO::WriteOperation> callback_factory_; 141 base::ScopedCallbackFactory<QuotaFileIO::WriteOperation> callback_factory_;
136 ScopedRunnableMethodFactory<QuotaFileIO::WriteOperation> runnable_factory_; 142 ScopedRunnableMethodFactory<QuotaFileIO::WriteOperation> runnable_factory_;
137 }; 143 };
138 144
139 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { 145 class QuotaFileIO::SetLengthOperation : public PendingOperationBase {
140 public: 146 public:
141 SetLengthOperation(QuotaFileIO* quota_io, 147 SetLengthOperation(QuotaFileIO* quota_io,
142 bool is_will_operation, 148 bool is_will_operation,
143 int64_t length, 149 int64_t length,
144 StatusCallback* callback) 150 StatusCallback* callback)
145 : PendingOperationBase(quota_io, is_will_operation), 151 : PendingOperationBase(quota_io, is_will_operation),
146 length_(length), 152 length_(length),
153 status_(base::PLATFORM_FILE_OK),
147 callback_(callback), 154 callback_(callback),
148 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 155 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
149 runnable_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} 156 runnable_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
150 virtual ~SetLengthOperation() {} 157 virtual ~SetLengthOperation() {}
151 158
152 virtual void Run() OVERRIDE { 159 virtual void Run() OVERRIDE {
153 DCHECK(quota_io_); 160 DCHECK(quota_io_);
154 if (quota_io_->CheckIfExceedsQuota(length_)) { 161 if (quota_io_->CheckIfExceedsQuota(length_)) {
155 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); 162 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE);
156 return; 163 return;
157 } 164 }
158 if (is_will_operation_) { 165 if (is_will_operation_) {
159 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( 166 base::MessageLoopProxy::CreateForCurrentThread()->PostTask(
160 FROM_HERE, runnable_factory_.NewRunnableMethod( 167 FROM_HERE, runnable_factory_.NewRunnableMethod(
161 &SetLengthOperation::DidFinish, 168 &SetLengthOperation::DidFinish, base::PLATFORM_FILE_OK));
162 base::PLATFORM_FILE_OK));
163 return; 169 return;
164 } 170 }
165 if (!base::FileUtilProxy::Truncate( 171 if (!base::FileUtilProxy::Truncate(
166 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), 172 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(),
167 quota_io_->file_, length_, 173 quota_io_->file_, length_,
168 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { 174 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) {
169 DidFail(base::PLATFORM_FILE_ERROR_FAILED); 175 DidFail(base::PLATFORM_FILE_ERROR_FAILED);
170 return; 176 return;
171 } 177 }
172 } 178 }
173 179
174 virtual void DidFail(PlatformFileError error) OVERRIDE { 180 virtual void DidFail(PlatformFileError error) OVERRIDE {
175 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( 181 base::MessageLoopProxy::CreateForCurrentThread()->PostTask(
176 FROM_HERE, runnable_factory_.NewRunnableMethod( 182 FROM_HERE, runnable_factory_.NewRunnableMethod(
177 &SetLengthOperation::DidFinish, error)); 183 &SetLengthOperation::DidFinish, error));
178 } 184 }
179 185
180 private: 186 private:
181 void DidFinish(PlatformFileError status) { 187 void DidFinish(PlatformFileError status) {
182 quota_io_->DidSetLength(status, length_); 188 quota_io_->DidSetLength(status, length_);
189 status_ = status;
190 base::MessageLoopProxy::CreateForCurrentThread()->PostTask(
191 FROM_HERE, runnable_factory_.NewRunnableMethod(
192 &SetLengthOperation::RunCallback));
193 }
194
195 void RunCallback() {
183 DCHECK(callback_.get()); 196 DCHECK(callback_.get());
184 callback_->Run(status); 197 callback_->Run(status_);
185 callback_.reset(); 198 callback_.reset();
186 delete this; 199 delete this;
187 } 200 }
188 201
189 int64_t length_; 202 int64_t length_;
203 PlatformFileError status_;
190 scoped_ptr<StatusCallback> callback_; 204 scoped_ptr<StatusCallback> callback_;
191 base::ScopedCallbackFactory<QuotaFileIO::SetLengthOperation> 205 base::ScopedCallbackFactory<QuotaFileIO::SetLengthOperation>
192 callback_factory_; 206 callback_factory_;
193 ScopedRunnableMethodFactory<QuotaFileIO::SetLengthOperation> 207 ScopedRunnableMethodFactory<QuotaFileIO::SetLengthOperation>
194 runnable_factory_; 208 runnable_factory_;
195 }; 209 };
196 210
197 // QuotaFileIO -------------------------------------------------------------- 211 // QuotaFileIO --------------------------------------------------------------
198 212
199 QuotaFileIO::QuotaFileIO( 213 QuotaFileIO::QuotaFileIO(
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 int64_t written_offset_end) { 346 int64_t written_offset_end) {
333 max_written_offset_ = std::max(max_written_offset_, written_offset_end); 347 max_written_offset_ = std::max(max_written_offset_, written_offset_end);
334 DCHECK_GT(inflight_operations_, 0); 348 DCHECK_GT(inflight_operations_, 0);
335 DCHECK(!pending_operations_.empty()); 349 DCHECK(!pending_operations_.empty());
336 // Fire callbacks for finished operations. 350 // Fire callbacks for finished operations.
337 while (!pending_operations_.empty()) { 351 while (!pending_operations_.empty()) {
338 WriteOperation* op = static_cast<WriteOperation*>( 352 WriteOperation* op = static_cast<WriteOperation*>(
339 pending_operations_.front()); 353 pending_operations_.front());
340 if (!op->finished()) 354 if (!op->finished())
341 break; 355 break;
342 op->RunCallback();
343 pending_operations_.pop_front(); 356 pending_operations_.pop_front();
357 op->RunCallbackSoon();
344 } 358 }
345 // If we have no more pending writes, notify the browser that we did 359 // If we have no more pending writes, notify the browser that we did
346 // update the file. 360 // update the file.
347 if (--inflight_operations_ == 0) { 361 if (--inflight_operations_ == 0) {
348 DCHECK(pending_operations_.empty()); 362 DCHECK(pending_operations_.empty());
349 int64_t growth = max_written_offset_ - cached_file_size_; 363 int64_t growth = max_written_offset_ - cached_file_size_;
350 growth = growth < 0 ? 0 : growth; 364 growth = growth < 0 ? 0 : growth;
351 instance_->delegate()->DidUpdateFile(file_url_, growth); 365 instance_->delegate()->DidUpdateFile(file_url_, growth);
352 max_written_offset_ = 0; 366 max_written_offset_ = 0;
353 } 367 }
354 } 368 }
355 369
356 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { 370 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) {
357 DCHECK_EQ(1, inflight_operations_); 371 DCHECK_EQ(1, inflight_operations_);
358 pending_operations_.pop_front(); 372 pending_operations_.pop_front();
359 DCHECK(pending_operations_.empty()); 373 DCHECK(pending_operations_.empty());
360 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : 374 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 :
361 new_file_size - cached_file_size_; 375 new_file_size - cached_file_size_;
362 instance_->delegate()->DidUpdateFile(file_url_, delta); 376 instance_->delegate()->DidUpdateFile(file_url_, delta);
363 inflight_operations_ = 0; 377 inflight_operations_ = 0;
364 } 378 }
365 379
366 } // namespace ppapi 380 } // namespace ppapi
367 } // namespace webkit 381 } // namespace webkit
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698