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

Side by Side Diff: content/child/shared_memory_data_consumer_handle.cc

Issue 1181573003: Set error on WebDataConsumerHandle while loading body. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@use-ipc-data-consumer
Patch Set: rebase Created 5 years, 6 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/child/shared_memory_data_consumer_handle.h" 5 #include "content/child/shared_memory_data_consumer_handle.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <deque> 8 #include <deque>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 46
47 using Result = blink::WebDataConsumerHandle::Result; 47 using Result = blink::WebDataConsumerHandle::Result;
48 48
49 class SharedMemoryDataConsumerHandle::Context final 49 class SharedMemoryDataConsumerHandle::Context final
50 : public base::RefCountedThreadSafe<Context> { 50 : public base::RefCountedThreadSafe<Context> {
51 public: 51 public:
52 Context() 52 Context()
53 : result_(Ok), 53 : result_(Ok),
54 first_offset_(0), 54 first_offset_(0),
55 client_(nullptr), 55 client_(nullptr),
56 is_handle_active_(true) {} 56 is_handle_active_(true),
57 is_two_phase_read_in_progress_(false) {}
57 58
58 bool IsEmpty() const { return queue_.empty(); } 59 bool IsEmpty() const { return queue_.empty(); }
59 void ClearIfNecessary() { 60 void ClearIfNecessary() {
60 if (!is_handle_locked() && !is_handle_active()) { 61 if (!is_handle_locked() && !is_handle_active()) {
61 // No one is interested in the contents. 62 // No one is interested in the contents.
62 Clear(); 63 Clear();
63 } 64 }
64 } 65 }
66 void ClearQueue() {
67 for (auto& data : queue_) {
68 delete data;
69 }
70 queue_.clear();
71 first_offset_ = 0;
72 }
65 RequestPeer::ThreadSafeReceivedData* Top() { return queue_.front(); } 73 RequestPeer::ThreadSafeReceivedData* Top() { return queue_.front(); }
66 void Push(scoped_ptr<RequestPeer::ThreadSafeReceivedData> data) { 74 void Push(scoped_ptr<RequestPeer::ThreadSafeReceivedData> data) {
67 queue_.push_back(data.release()); 75 queue_.push_back(data.release());
68 } 76 }
69 size_t first_offset() const { return first_offset_; } 77 size_t first_offset() const { return first_offset_; }
70 Result result() const { return result_; } 78 Result result() const { return result_; }
71 void set_result(Result r) { result_ = r; } 79 void set_result(Result r) { result_ = r; }
72 void AcquireReaderLock(Client* client) { 80 void AcquireReaderLock(Client* client) {
73 DCHECK(!notification_task_runner_); 81 DCHECK(!notification_task_runner_);
74 DCHECK(!client_); 82 DCHECK(!client_);
(...skipping 21 matching lines...) Expand all
96 void set_is_handle_active(bool b) { is_handle_active_ = b; } 104 void set_is_handle_active(bool b) { is_handle_active_ = b; }
97 void Consume(size_t s) { 105 void Consume(size_t s) {
98 first_offset_ += s; 106 first_offset_ += s;
99 auto top = Top(); 107 auto top = Top();
100 if (static_cast<size_t>(top->length()) <= first_offset_) { 108 if (static_cast<size_t>(top->length()) <= first_offset_) {
101 delete top; 109 delete top;
102 queue_.pop_front(); 110 queue_.pop_front();
103 first_offset_ = 0; 111 first_offset_ = 0;
104 } 112 }
105 } 113 }
114 bool is_two_phase_read_in_progress() const {
115 return is_two_phase_read_in_progress_;
116 }
117 void set_is_two_phase_read_in_progress(bool b) {
118 is_two_phase_read_in_progress_ = b;
119 }
106 base::Lock& lock() { return lock_; } 120 base::Lock& lock() { return lock_; }
107 121
108 private: 122 private:
109 void NotifyInternal(bool repost) { 123 void NotifyInternal(bool repost) {
110 // Note that this function is not protected by |lock_|. 124 // Note that this function is not protected by |lock_|.
111 125
112 auto runner = notification_task_runner_; 126 auto runner = notification_task_runner_;
113 if (!runner) 127 if (!runner)
114 return; 128 return;
115 129
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 // |result_| stores the ultimate state of this handle if it has. Otherwise, 161 // |result_| stores the ultimate state of this handle if it has. Otherwise,
148 // |Ok| is set. 162 // |Ok| is set.
149 Result result_; 163 Result result_;
150 // TODO(yhirano): Use std::deque<scoped_ptr<ThreadSafeReceivedData>> 164 // TODO(yhirano): Use std::deque<scoped_ptr<ThreadSafeReceivedData>>
151 // once it is allowed. 165 // once it is allowed.
152 std::deque<RequestPeer::ThreadSafeReceivedData*> queue_; 166 std::deque<RequestPeer::ThreadSafeReceivedData*> queue_;
153 size_t first_offset_; 167 size_t first_offset_;
154 Client* client_; 168 Client* client_;
155 scoped_refptr<base::SingleThreadTaskRunner> notification_task_runner_; 169 scoped_refptr<base::SingleThreadTaskRunner> notification_task_runner_;
156 bool is_handle_active_; 170 bool is_handle_active_;
171 bool is_two_phase_read_in_progress_;
157 172
158 DISALLOW_COPY_AND_ASSIGN(Context); 173 DISALLOW_COPY_AND_ASSIGN(Context);
159 }; 174 };
160 175
161 SharedMemoryDataConsumerHandle::Writer::Writer( 176 SharedMemoryDataConsumerHandle::Writer::Writer(
162 const scoped_refptr<Context>& context, 177 const scoped_refptr<Context>& context,
163 BackpressureMode mode) 178 BackpressureMode mode)
164 : context_(context), mode_(mode) { 179 : context_(context), mode_(mode) {
165 } 180 }
166 181
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 base::AutoLock lock(context_->lock()); 220 base::AutoLock lock(context_->lock());
206 if (context_->result() == Ok) { 221 if (context_->result() == Ok) {
207 context_->set_result(Done); 222 context_->set_result(Done);
208 needs_notification = context_->IsEmpty(); 223 needs_notification = context_->IsEmpty();
209 } 224 }
210 } 225 }
211 if (needs_notification) 226 if (needs_notification)
212 context_->Notify(); 227 context_->Notify();
213 } 228 }
214 229
230 void SharedMemoryDataConsumerHandle::Writer::Error() {
231 bool needs_notification = false;
232
233 {
234 base::AutoLock lock(context_->lock());
235 if (context_->result() == Ok) {
236 // TODO(yhirano): Use an appropriate error code other than
237 // UnexpectedError.
238 context_->set_result(UnexpectedError);
239
240 if (!context_->is_two_phase_read_in_progress()) {
241 // If we are in two-phase read session, we cannot discard the data.
242 // Otherwise, clear the data.
hiroshige 2015/06/18 07:01:20 Please mention in the comment when/how ClearQueue(
yhirano 2015/06/18 08:13:33 Done.
243 context_->ClearQueue();
244 }
245
246 needs_notification = true;
247 }
248 }
249 if (needs_notification)
250 context_->Notify();
251 }
252
215 SharedMemoryDataConsumerHandle::ReaderImpl::ReaderImpl( 253 SharedMemoryDataConsumerHandle::ReaderImpl::ReaderImpl(
216 scoped_refptr<Context> context, 254 scoped_refptr<Context> context,
217 Client* client) 255 Client* client)
218 : context_(context) { 256 : context_(context) {
219 base::AutoLock lock(context_->lock()); 257 base::AutoLock lock(context_->lock());
220 DCHECK(!context_->is_handle_locked()); 258 DCHECK(!context_->is_handle_locked());
221 context_->AcquireReaderLock(client); 259 context_->AcquireReaderLock(client);
222 } 260 }
223 261
224 SharedMemoryDataConsumerHandle::ReaderImpl::~ReaderImpl() { 262 SharedMemoryDataConsumerHandle::ReaderImpl::~ReaderImpl() {
225 base::AutoLock lock(context_->lock()); 263 base::AutoLock lock(context_->lock());
226 context_->ReleaseReaderLock(); 264 context_->ReleaseReaderLock();
227 context_->ClearIfNecessary(); 265 context_->ClearIfNecessary();
228 } 266 }
229 267
230 Result SharedMemoryDataConsumerHandle::ReaderImpl::read( 268 Result SharedMemoryDataConsumerHandle::ReaderImpl::read(
231 void* data, 269 void* data,
232 size_t size, 270 size_t size,
233 Flags flags, 271 Flags flags,
234 size_t* read_size_to_return) { 272 size_t* read_size_to_return) {
235 base::AutoLock lock(context_->lock()); 273 base::AutoLock lock(context_->lock());
236 274
237 size_t total_read_size = 0; 275 size_t total_read_size = 0;
238 *read_size_to_return = 0; 276 *read_size_to_return = 0;
277
278 if (context_->is_two_phase_read_in_progress())
279 context_->set_result(UnexpectedError);
hiroshige 2015/06/18 07:01:21 Is this change for setting errors on read()/beginR
yhirano 2015/06/18 08:13:33 Done. By the way, I added a condition to stabilize
280
239 if (context_->result() != Ok && context_->result() != Done) 281 if (context_->result() != Ok && context_->result() != Done)
240 return context_->result(); 282 return context_->result();
241 283
242 while (!context_->IsEmpty() && total_read_size < size) { 284 while (!context_->IsEmpty() && total_read_size < size) {
243 const auto& top = context_->Top(); 285 const auto& top = context_->Top();
244 size_t readable = top->length() - context_->first_offset(); 286 size_t readable = top->length() - context_->first_offset();
245 size_t writable = size - total_read_size; 287 size_t writable = size - total_read_size;
246 size_t read_size = std::min(readable, writable); 288 size_t read_size = std::min(readable, writable);
247 const char* begin = top->payload() + context_->first_offset(); 289 const char* begin = top->payload() + context_->first_offset();
248 std::copy(begin, begin + read_size, 290 std::copy(begin, begin + read_size,
249 static_cast<char*>(data) + total_read_size); 291 static_cast<char*>(data) + total_read_size);
250 total_read_size += read_size; 292 total_read_size += read_size;
251 context_->Consume(read_size); 293 context_->Consume(read_size);
252 } 294 }
253 *read_size_to_return = total_read_size; 295 *read_size_to_return = total_read_size;
254 return total_read_size ? Ok : context_->result() == Done ? Done : ShouldWait; 296 return total_read_size ? Ok : context_->result() == Done ? Done : ShouldWait;
255 } 297 }
256 298
257 Result SharedMemoryDataConsumerHandle::ReaderImpl::beginRead( 299 Result SharedMemoryDataConsumerHandle::ReaderImpl::beginRead(
258 const void** buffer, 300 const void** buffer,
259 Flags flags, 301 Flags flags,
260 size_t* available) { 302 size_t* available) {
261 *buffer = nullptr; 303 *buffer = nullptr;
262 *available = 0; 304 *available = 0;
263 305
264 base::AutoLock lock(context_->lock()); 306 base::AutoLock lock(context_->lock());
265 307
308 if (context_->is_two_phase_read_in_progress())
309 context_->set_result(UnexpectedError);
hiroshige 2015/06/18 07:01:21 ditto.
yhirano 2015/06/18 08:13:33 Done.
310
266 if (context_->result() != Ok && context_->result() != Done) 311 if (context_->result() != Ok && context_->result() != Done)
267 return context_->result(); 312 return context_->result();
268 313
269 if (context_->IsEmpty()) 314 if (context_->IsEmpty())
270 return context_->result() == Done ? Done : ShouldWait; 315 return context_->result() == Done ? Done : ShouldWait;
271 316
317 context_->set_is_two_phase_read_in_progress(true);
272 const auto& top = context_->Top(); 318 const auto& top = context_->Top();
273 *buffer = top->payload() + context_->first_offset(); 319 *buffer = top->payload() + context_->first_offset();
274 *available = top->length() - context_->first_offset(); 320 *available = top->length() - context_->first_offset();
275 321
276 return Ok; 322 return Ok;
277 } 323 }
278 324
279 Result SharedMemoryDataConsumerHandle::ReaderImpl::endRead(size_t read_size) { 325 Result SharedMemoryDataConsumerHandle::ReaderImpl::endRead(size_t read_size) {
280 base::AutoLock lock(context_->lock()); 326 base::AutoLock lock(context_->lock());
281 327
282 if (context_->IsEmpty()) 328 if (!context_->is_two_phase_read_in_progress())
283 return UnexpectedError; 329 return UnexpectedError;
hiroshige 2015/06/18 07:01:20 Can/should we call ClearQueue() in this then claus
yhirano 2015/06/18 08:13:33 I do not want to do so, because it may complicate
yhirano 2015/06/18 08:14:51 Correction: I added early-clear when errored
hiroshige 2015/06/18 08:35:11 OK.
284 330
285 context_->Consume(read_size); 331 context_->set_is_two_phase_read_in_progress(false);
332 if (context_->result() != Ok && context_->result() != Done) {
333 // We have an error, so we can discard the stored data.
334 context_->ClearQueue();
335 } else {
336 context_->Consume(read_size);
337 }
338
286 return Ok; 339 return Ok;
287 } 340 }
288 341
289 SharedMemoryDataConsumerHandle::SharedMemoryDataConsumerHandle( 342 SharedMemoryDataConsumerHandle::SharedMemoryDataConsumerHandle(
290 BackpressureMode mode, 343 BackpressureMode mode,
291 scoped_ptr<Writer>* writer) 344 scoped_ptr<Writer>* writer)
292 : context_(new Context) { 345 : context_(new Context) {
293 writer->reset(new Writer(context_, mode)); 346 writer->reset(new Writer(context_, mode));
294 } 347 }
295 348
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 DCHECK(context_->IsReaderBoundToCurrentThread()); 412 DCHECK(context_->IsReaderBoundToCurrentThread());
360 needs_unlock = true; 413 needs_unlock = true;
361 } 414 }
362 } 415 }
363 if (needs_unlock) { 416 if (needs_unlock) {
364 reader_.reset(); 417 reader_.reset();
365 } 418 }
366 } 419 }
367 420
368 } // namespace content 421 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698