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

Side by Side Diff: content/browser/byte_stream.cc

Issue 22908008: Limit the total memory usage for Stream instances (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: creis's comments Created 7 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 | « content/browser/byte_stream.h ('k') | content/browser/byte_stream_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 "content/browser/byte_stream.h" 5 #include "content/browser/byte_stream.h"
6 6
7 #include <deque> 7 #include <deque>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 void SetPeer(ByteStreamReaderImpl* peer, 54 void SetPeer(ByteStreamReaderImpl* peer,
55 scoped_refptr<base::SequencedTaskRunner> peer_task_runner, 55 scoped_refptr<base::SequencedTaskRunner> peer_task_runner,
56 scoped_refptr<LifetimeFlag> peer_lifetime_flag); 56 scoped_refptr<LifetimeFlag> peer_lifetime_flag);
57 57
58 // Overridden from ByteStreamWriter. 58 // Overridden from ByteStreamWriter.
59 virtual bool Write(scoped_refptr<net::IOBuffer> buffer, 59 virtual bool Write(scoped_refptr<net::IOBuffer> buffer,
60 size_t byte_count) OVERRIDE; 60 size_t byte_count) OVERRIDE;
61 virtual void Flush() OVERRIDE; 61 virtual void Flush() OVERRIDE;
62 virtual void Close(int status) OVERRIDE; 62 virtual void Close(int status) OVERRIDE;
63 virtual void RegisterCallback(const base::Closure& source_callback) OVERRIDE; 63 virtual void RegisterCallback(const base::Closure& source_callback) OVERRIDE;
64 virtual size_t GetTotalBufferedBytes() const OVERRIDE;
64 65
65 // PostTask target from |ByteStreamReaderImpl::MaybeUpdateInput|. 66 // PostTask target from |ByteStreamReaderImpl::MaybeUpdateInput|.
66 static void UpdateWindow(scoped_refptr<LifetimeFlag> lifetime_flag, 67 static void UpdateWindow(scoped_refptr<LifetimeFlag> lifetime_flag,
67 ByteStreamWriterImpl* target, 68 ByteStreamWriterImpl* target,
68 size_t bytes_consumed); 69 size_t bytes_consumed);
69 70
70 private: 71 private:
71 // Called from UpdateWindow when object existence has been validated. 72 // Called from UpdateWindow when object existence has been validated.
72 void UpdateWindowInternal(size_t bytes_consumed); 73 void UpdateWindowInternal(size_t bytes_consumed);
73 74
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 scoped_refptr<LifetimeFlag> peer_lifetime_flag) { 203 scoped_refptr<LifetimeFlag> peer_lifetime_flag) {
203 peer_ = peer; 204 peer_ = peer;
204 peer_task_runner_ = peer_task_runner; 205 peer_task_runner_ = peer_task_runner;
205 peer_lifetime_flag_ = peer_lifetime_flag; 206 peer_lifetime_flag_ = peer_lifetime_flag;
206 } 207 }
207 208
208 bool ByteStreamWriterImpl::Write( 209 bool ByteStreamWriterImpl::Write(
209 scoped_refptr<net::IOBuffer> buffer, size_t byte_count) { 210 scoped_refptr<net::IOBuffer> buffer, size_t byte_count) {
210 DCHECK(my_task_runner_->RunsTasksOnCurrentThread()); 211 DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
211 212
213 // Check overflow.
214 //
215 // TODO(tyoshino): Discuss with content/browser/download developer and if
216 // they're fine with, set smaller limit and make it configurable.
217 size_t space_limit = std::numeric_limits<size_t>::max() -
218 GetTotalBufferedBytes();
219 if (byte_count > space_limit) {
220 // TODO(tyoshino): Tell the user that Write() failed.
221 // Ignore input.
222 return false;
223 }
224
212 input_contents_.push_back(std::make_pair(buffer, byte_count)); 225 input_contents_.push_back(std::make_pair(buffer, byte_count));
213 input_contents_size_ += byte_count; 226 input_contents_size_ += byte_count;
214 227
215 // Arbitrarily, we buffer to a third of the total size before sending. 228 // Arbitrarily, we buffer to a third of the total size before sending.
216 if (input_contents_size_ > total_buffer_size_ / kFractionBufferBeforeSending) 229 if (input_contents_size_ > total_buffer_size_ / kFractionBufferBeforeSending)
217 PostToPeer(false, 0); 230 PostToPeer(false, 0);
218 231
219 return (input_contents_size_ + output_size_used_ <= total_buffer_size_); 232 return GetTotalBufferedBytes() <= total_buffer_size_;
220 } 233 }
221 234
222 void ByteStreamWriterImpl::Flush() { 235 void ByteStreamWriterImpl::Flush() {
223 DCHECK(my_task_runner_->RunsTasksOnCurrentThread()); 236 DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
224 if (input_contents_size_ > 0) 237 if (input_contents_size_ > 0)
225 PostToPeer(false, 0); 238 PostToPeer(false, 0);
226 } 239 }
227 240
228 void ByteStreamWriterImpl::Close(int status) { 241 void ByteStreamWriterImpl::Close(int status) {
229 DCHECK(my_task_runner_->RunsTasksOnCurrentThread()); 242 DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
230 PostToPeer(true, status); 243 PostToPeer(true, status);
231 } 244 }
232 245
233 void ByteStreamWriterImpl::RegisterCallback( 246 void ByteStreamWriterImpl::RegisterCallback(
234 const base::Closure& source_callback) { 247 const base::Closure& source_callback) {
235 DCHECK(my_task_runner_->RunsTasksOnCurrentThread()); 248 DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
236 space_available_callback_ = source_callback; 249 space_available_callback_ = source_callback;
237 } 250 }
238 251
252 size_t ByteStreamWriterImpl::GetTotalBufferedBytes() const {
253 DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
254 // This sum doesn't overflow since Write() fails if this sum is going to
255 // overflow.
256 return input_contents_size_ + output_size_used_;
257 }
258
239 // static 259 // static
240 void ByteStreamWriterImpl::UpdateWindow( 260 void ByteStreamWriterImpl::UpdateWindow(
241 scoped_refptr<LifetimeFlag> lifetime_flag, ByteStreamWriterImpl* target, 261 scoped_refptr<LifetimeFlag> lifetime_flag, ByteStreamWriterImpl* target,
242 size_t bytes_consumed) { 262 size_t bytes_consumed) {
243 // If the target object isn't alive anymore, we do nothing. 263 // If the target object isn't alive anymore, we do nothing.
244 if (!lifetime_flag->is_alive) return; 264 if (!lifetime_flag->is_alive) return;
245 265
246 target->UpdateWindowInternal(bytes_consumed); 266 target->UpdateWindowInternal(bytes_consumed);
247 } 267 }
248 268
249 void ByteStreamWriterImpl::UpdateWindowInternal(size_t bytes_consumed) { 269 void ByteStreamWriterImpl::UpdateWindowInternal(size_t bytes_consumed) {
250 DCHECK(my_task_runner_->RunsTasksOnCurrentThread()); 270 DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
271
272 bool was_above_limit = GetTotalBufferedBytes() > total_buffer_size_;
273
251 DCHECK_GE(output_size_used_, bytes_consumed); 274 DCHECK_GE(output_size_used_, bytes_consumed);
252 output_size_used_ -= bytes_consumed; 275 output_size_used_ -= bytes_consumed;
253 276
254 // Callback if we were above the limit and we're now <= to it. 277 // Callback if we were above the limit and we're now <= to it.
255 size_t total_known_size_used = 278 bool no_longer_above_limit = GetTotalBufferedBytes() <= total_buffer_size_;
256 input_contents_size_ + output_size_used_;
257 279
258 if (total_known_size_used <= total_buffer_size_ && 280 if (no_longer_above_limit && was_above_limit &&
259 (total_known_size_used + bytes_consumed > total_buffer_size_) &&
260 !space_available_callback_.is_null()) 281 !space_available_callback_.is_null())
261 space_available_callback_.Run(); 282 space_available_callback_.Run();
262 } 283 }
263 284
264 void ByteStreamWriterImpl::PostToPeer(bool complete, int status) { 285 void ByteStreamWriterImpl::PostToPeer(bool complete, int status) {
265 DCHECK(my_task_runner_->RunsTasksOnCurrentThread()); 286 DCHECK(my_task_runner_->RunsTasksOnCurrentThread());
266 // Valid contexts in which to call. 287 // Valid contexts in which to call.
267 DCHECK(complete || 0 != input_contents_size_); 288 DCHECK(complete || 0 != input_contents_size_);
268 289
269 scoped_ptr<ContentVector> transfer_buffer; 290 scoped_ptr<ContentVector> transfer_buffer;
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 ByteStreamReaderImpl* out = new ByteStreamReaderImpl( 453 ByteStreamReaderImpl* out = new ByteStreamReaderImpl(
433 output_task_runner, output_flag, buffer_size); 454 output_task_runner, output_flag, buffer_size);
434 455
435 in->SetPeer(out, output_task_runner, output_flag); 456 in->SetPeer(out, output_task_runner, output_flag);
436 out->SetPeer(in, input_task_runner, input_flag); 457 out->SetPeer(in, input_task_runner, input_flag);
437 input->reset(in); 458 input->reset(in);
438 output->reset(out); 459 output->reset(out);
439 } 460 }
440 461
441 } // namespace content 462 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/byte_stream.h ('k') | content/browser/byte_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698