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

Side by Side Diff: webkit/glue/media/buffered_data_source.cc

Issue 269002: Report stalled event correctly for <video> (Closed)
Patch Set: comments Created 11 years, 2 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 (c) 2009 The Chromium Authors. All rights reserved. Use of this 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the 2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file. 3 // LICENSE file.
4 4
5 #include "base/compiler_specific.h" 5 #include "base/compiler_specific.h"
6 #include "base/message_loop.h" 6 #include "base/message_loop.h"
7 #include "base/process_util.h" 7 #include "base/process_util.h"
8 #include "base/stl_util-inl.h" 8 #include "base/stl_util-inl.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "chrome/common/extensions/url_pattern.h" 10 #include "chrome/common/extensions/url_pattern.h"
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 read_position_(0), 91 read_position_(0),
92 read_size_(0), 92 read_size_(0),
93 read_buffer_(NULL), 93 read_buffer_(NULL),
94 first_offset_(0), 94 first_offset_(0),
95 last_offset_(0) { 95 last_offset_(0) {
96 } 96 }
97 97
98 BufferedResourceLoader::~BufferedResourceLoader() { 98 BufferedResourceLoader::~BufferedResourceLoader() {
99 } 99 }
100 100
101 void BufferedResourceLoader::Start(net::CompletionCallback* start_callback) { 101 void BufferedResourceLoader::Start(net::CompletionCallback* start_callback,
102 Callback0::Type* event_callback) {
scherkus (not reviewing) 2009/10/15 23:51:38 use NetworkEventCallback instead
102 // Make sure we have not started. 103 // Make sure we have not started.
103 DCHECK(!bridge_.get()); 104 DCHECK(!bridge_.get());
104 DCHECK(!start_callback_.get()); 105 DCHECK(!start_callback_.get());
106 DCHECK(!event_callback_.get());
105 DCHECK(start_callback); 107 DCHECK(start_callback);
108 DCHECK(event_callback);
106 109
107 start_callback_.reset(start_callback); 110 start_callback_.reset(start_callback);
111 event_callback_.reset(event_callback);
108 112
109 if (first_byte_position_ != kPositionNotSpecified) { 113 if (first_byte_position_ != kPositionNotSpecified) {
110 range_requested_ = true; 114 range_requested_ = true;
111 // TODO(hclam): server may not support range request so |offset_| may not 115 // TODO(hclam): server may not support range request so |offset_| may not
112 // equal to |first_byte_position_|. 116 // equal to |first_byte_position_|.
113 offset_ = first_byte_position_; 117 offset_ = first_byte_position_;
114 } 118 }
115 119
116 // Creates the bridge on render thread since we can only access 120 // Creates the bridge on render thread since we can only access
117 // ResourceDispatcher on this thread. 121 // ResourceDispatcher on this thread.
118 bridge_.reset( 122 bridge_.reset(
119 bridge_factory_->CreateBridge( 123 bridge_factory_->CreateBridge(
120 url_, 124 url_,
121 IsMediaCacheEnabled() ? net::LOAD_NORMAL : net::LOAD_BYPASS_CACHE, 125 IsMediaCacheEnabled() ? net::LOAD_NORMAL : net::LOAD_BYPASS_CACHE,
122 first_byte_position_, 126 first_byte_position_,
123 last_byte_position_)); 127 last_byte_position_));
124 128
125 // Increment the reference count right before we start the request. This 129 // Increment the reference count right before we start the request. This
126 // reference will be release when this request has ended. 130 // reference will be release when this request has ended.
127 AddRef(); 131 AddRef();
128 132
129 // And start the resource loading. 133 // And start the resource loading.
130 bridge_->Start(this); 134 bridge_->Start(this);
131 } 135 }
132 136
133 void BufferedResourceLoader::Stop() { 137 void BufferedResourceLoader::Stop() {
134 // Reset callbacks. 138 // Reset callbacks.
135 start_callback_.reset(); 139 start_callback_.reset();
140 event_callback_.reset();
136 read_callback_.reset(); 141 read_callback_.reset();
137 142
143 // Use the internal buffer to signal that we have been stopped.
144 // TODO(hclam): Not so pretty to do this.
145 if (!buffer_.get())
146 return;
147
138 // Destroy internal buffer. 148 // Destroy internal buffer.
139 buffer_.reset(); 149 buffer_.reset();
140 150
141 if (bridge_.get()) { 151 if (bridge_.get()) {
142 // Cancel the request. This method call will cancel the request 152 // Cancel the request. This method call will cancel the request
143 // asynchronously. We may still get data or messages until we receive 153 // asynchronously. We may still get data or messages until we receive
144 // a response completed message. 154 // a response completed message.
145 if (deferred_) 155 if (deferred_)
146 bridge_->SetDefersLoading(false); 156 bridge_->SetDefersLoading(false);
147 deferred_ = false; 157 deferred_ = false;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 202
193 // If we expected the read request to be fulfilled later, returns 203 // If we expected the read request to be fulfilled later, returns
194 // immediately and let more data to flow in. 204 // immediately and let more data to flow in.
195 if (WillFulfillRead()) 205 if (WillFulfillRead())
196 return; 206 return;
197 207
198 // Make a callback to report failure. 208 // Make a callback to report failure.
199 DoneRead(net::ERR_CACHE_MISS); 209 DoneRead(net::ERR_CACHE_MISS);
200 } 210 }
201 211
212 int64 BufferedResourceLoader::GetBufferedFirstBytePosition() {
213 if (buffer_.get())
214 return offset_ - static_cast<int>(buffer_->backward_bytes());
215 return kPositionNotSpecified;
216 }
217
218 int64 BufferedResourceLoader::GetBufferedLastBytePosition() {
219 if (buffer_.get())
220 return offset_ + static_cast<int>(buffer_->forward_bytes()) - 1;
221 return kPositionNotSpecified;
222 }
223
202 ///////////////////////////////////////////////////////////////////////////// 224 /////////////////////////////////////////////////////////////////////////////
203 // BufferedResourceLoader, 225 // BufferedResourceLoader,
204 // webkit_glue::ResourceLoaderBridge::Peer implementations 226 // webkit_glue::ResourceLoaderBridge::Peer implementations
205 bool BufferedResourceLoader::OnReceivedRedirect( 227 bool BufferedResourceLoader::OnReceivedRedirect(
206 const GURL& new_url, 228 const GURL& new_url,
207 const webkit_glue::ResourceLoaderBridge::ResponseInfo& info) { 229 const webkit_glue::ResourceLoaderBridge::ResponseInfo& info) {
208 DCHECK(bridge_.get()); 230 DCHECK(bridge_.get());
209 231
210 // Save the new URL. 232 // Save the new URL.
211 url_ = new_url; 233 url_ = new_url;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 // Writes more data to |buffer_|. 315 // Writes more data to |buffer_|.
294 buffer_->Append(len, reinterpret_cast<const uint8*>(data)); 316 buffer_->Append(len, reinterpret_cast<const uint8*>(data));
295 317
296 // If there is an active read request, try to fulfill the request. 318 // If there is an active read request, try to fulfill the request.
297 if (HasPendingRead() && CanFulfillRead()) { 319 if (HasPendingRead() && CanFulfillRead()) {
298 ReadInternal(); 320 ReadInternal();
299 } 321 }
300 322
301 // At last see if the buffer is full and we need to defer the downloading. 323 // At last see if the buffer is full and we need to defer the downloading.
302 EnableDeferIfNeeded(); 324 EnableDeferIfNeeded();
325
326 // Notify that we have received some data.
327 NotifyNetworkEvent();
303 } 328 }
304 329
305 void BufferedResourceLoader::OnCompletedRequest( 330 void BufferedResourceLoader::OnCompletedRequest(
306 const URLRequestStatus& status, const std::string& security_info) { 331 const URLRequestStatus& status, const std::string& security_info) {
307 DCHECK(bridge_.get()); 332 DCHECK(bridge_.get());
308 333
309 // Saves the information that the request has completed. 334 // Saves the information that the request has completed.
310 completed_ = true; 335 completed_ = true;
311 336
312 // If there is a start callback, calls it. 337 // If there is a start callback, calls it.
(...skipping 15 matching lines...) Expand all
328 DoneRead(net::ERR_CACHE_MISS); 353 DoneRead(net::ERR_CACHE_MISS);
329 } else { 354 } else {
330 // If the request has failed, then fail the read. 355 // If the request has failed, then fail the read.
331 DoneRead(net::ERR_FAILED); 356 DoneRead(net::ERR_FAILED);
332 } 357 }
333 } 358 }
334 359
335 // There must not be any outstanding read request. 360 // There must not be any outstanding read request.
336 DCHECK(!HasPendingRead()); 361 DCHECK(!HasPendingRead());
337 362
363 // Notify that network response is completed.
364 NotifyNetworkEvent();
365
338 // We incremented the reference count when the loader was started. We balance 366 // We incremented the reference count when the loader was started. We balance
339 // that reference here so that we get destroyed. This is also the only safe 367 // that reference here so that we get destroyed. This is also the only safe
340 // place to destroy the ResourceLoaderBridge. 368 // place to destroy the ResourceLoaderBridge.
341 bridge_.reset(); 369 bridge_.reset();
342 Release(); 370 Release();
343 } 371 }
344 372
345 ///////////////////////////////////////////////////////////////////////////// 373 /////////////////////////////////////////////////////////////////////////////
346 // BufferedResourceLoader, private 374 // BufferedResourceLoader, private
347 void BufferedResourceLoader::EnableDeferIfNeeded() { 375 void BufferedResourceLoader::EnableDeferIfNeeded() {
348 if (!deferred_ && 376 if (!deferred_ &&
349 buffer_->forward_bytes() >= buffer_->forward_capacity()) { 377 buffer_->forward_bytes() >= buffer_->forward_capacity()) {
350 deferred_ = true; 378 deferred_ = true;
351 379
352 if (bridge_.get()) 380 if (bridge_.get())
353 bridge_->SetDefersLoading(true); 381 bridge_->SetDefersLoading(true);
382
383 NotifyNetworkEvent();
354 } 384 }
355 } 385 }
356 386
357 void BufferedResourceLoader::DisableDeferIfNeeded() { 387 void BufferedResourceLoader::DisableDeferIfNeeded() {
358 if (deferred_ && 388 if (deferred_ &&
359 buffer_->forward_bytes() < buffer_->forward_capacity() / 2) { 389 buffer_->forward_bytes() < buffer_->forward_capacity() / 2) {
360 deferred_ = false; 390 deferred_ = false;
361 391
362 if (bridge_.get()) 392 if (bridge_.get())
363 bridge_->SetDefersLoading(false); 393 bridge_->SetDefersLoading(false);
394
395 NotifyNetworkEvent();
364 } 396 }
365 } 397 }
366 398
367 bool BufferedResourceLoader::CanFulfillRead() { 399 bool BufferedResourceLoader::CanFulfillRead() {
368 // If we are reading too far in the backward direction. 400 // If we are reading too far in the backward direction.
369 if (first_offset_ < 0 && 401 if (first_offset_ < 0 &&
370 first_offset_ + static_cast<int>(buffer_->backward_bytes()) < 0) 402 first_offset_ + static_cast<int>(buffer_->backward_bytes()) < 0)
371 return false; 403 return false;
372 404
373 // If the start offset is too far ahead. 405 // If the start offset is too far ahead.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 DCHECK(ret); 443 DCHECK(ret);
412 444
413 // Then do the read. 445 // Then do the read.
414 int read = static_cast<int>(buffer_->Read(read_size_, read_buffer_)); 446 int read = static_cast<int>(buffer_->Read(read_size_, read_buffer_));
415 offset_ += first_offset_ + read; 447 offset_ += first_offset_ + read;
416 448
417 // And report with what we have read. 449 // And report with what we have read.
418 DoneRead(read); 450 DoneRead(read);
419 } 451 }
420 452
421 void BufferedResourceLoader::DoneRead(int error) {
422 read_callback_->RunWithParams(Tuple1<int>(error));
423 read_callback_.reset();
424 read_position_ = 0;
425 read_size_ = 0;
426 read_buffer_ = NULL;
427 first_offset_ = 0;
428 last_offset_ = 0;
429 }
430
431 void BufferedResourceLoader::DoneStart(int error) {
432 start_callback_->RunWithParams(Tuple1<int>(error));
433 start_callback_.reset();
434 }
435
436 bool BufferedResourceLoader::VerifyPartialResponse( 453 bool BufferedResourceLoader::VerifyPartialResponse(
437 const ResourceLoaderBridge::ResponseInfo& info) { 454 const ResourceLoaderBridge::ResponseInfo& info) {
438 int64 first_byte_position, last_byte_position, instance_size; 455 int64 first_byte_position, last_byte_position, instance_size;
439 if (!info.headers->GetContentRange(&first_byte_position, 456 if (!info.headers->GetContentRange(&first_byte_position,
440 &last_byte_position, 457 &last_byte_position,
441 &instance_size)) { 458 &instance_size)) {
442 return false; 459 return false;
443 } 460 }
444 461
445 if (instance_size != kPositionNotSpecified) 462 if (instance_size != kPositionNotSpecified)
446 instance_size_ = instance_size; 463 instance_size_ = instance_size;
447 464
448 if (first_byte_position_ != -1 && 465 if (first_byte_position_ != -1 &&
449 first_byte_position_ != first_byte_position) { 466 first_byte_position_ != first_byte_position) {
450 return false; 467 return false;
451 } 468 }
452 469
453 // TODO(hclam): I should also check |last_byte_position|, but since 470 // TODO(hclam): I should also check |last_byte_position|, but since
454 // we will never make such a request that it is ok to leave it unimplemented. 471 // we will never make such a request that it is ok to leave it unimplemented.
455 return true; 472 return true;
456 } 473 }
457 474
458 ////////////////////////////////////////////////////////////////////////////// 475 void BufferedResourceLoader::DoneRead(int error) {
476 read_callback_->RunWithParams(Tuple1<int>(error));
477 read_callback_.reset();
478 read_position_ = 0;
479 read_size_ = 0;
480 read_buffer_ = NULL;
481 first_offset_ = 0;
482 last_offset_ = 0;
483 }
484
485 void BufferedResourceLoader::DoneStart(int error) {
486 start_callback_->RunWithParams(Tuple1<int>(error));
487 start_callback_.reset();
488 }
489
490 void BufferedResourceLoader::NotifyNetworkEvent() {
491 if (event_callback_.get())
492 event_callback_->Run();
493 }
494
495 /////////////////////////////////////////////////////////////////////////////
459 // BufferedDataSource, protected 496 // BufferedDataSource, protected
460 BufferedDataSource::BufferedDataSource( 497 BufferedDataSource::BufferedDataSource(
461 MessageLoop* render_loop, 498 MessageLoop* render_loop,
462 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory) 499 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory)
463 : total_bytes_(kPositionNotSpecified), 500 : total_bytes_(kPositionNotSpecified),
501 loaded_(false),
464 streaming_(false), 502 streaming_(false),
465 bridge_factory_(bridge_factory), 503 bridge_factory_(bridge_factory),
466 loader_(NULL), 504 loader_(NULL),
505 network_activity_(false),
467 initialize_callback_(NULL), 506 initialize_callback_(NULL),
468 read_callback_(NULL), 507 read_callback_(NULL),
469 read_position_(0), 508 read_position_(0),
470 read_size_(0), 509 read_size_(0),
471 read_buffer_(NULL), 510 read_buffer_(NULL),
472 read_attempts_(0), 511 read_attempts_(0),
473 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), 512 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]),
474 intermediate_read_buffer_size_(kInitialReadBufferSize), 513 intermediate_read_buffer_size_(kInitialReadBufferSize),
475 render_loop_(render_loop), 514 render_loop_(render_loop),
476 stopped_(false), 515 stop_signal_received_(false),
477 stop_task_finished_(false) { 516 stopped_on_render_loop_(false) {
478 } 517 }
479 518
480 BufferedDataSource::~BufferedDataSource() { 519 BufferedDataSource::~BufferedDataSource() {
481 } 520 }
482 521
483 // A factory method to create BufferedResourceLoader using the read parameters. 522 // A factory method to create BufferedResourceLoader using the read parameters.
484 // This method can be overrided to inject mock BufferedResourceLoader object 523 // This method can be overrided to inject mock BufferedResourceLoader object
485 // for testing purpose. 524 // for testing purpose.
486 BufferedResourceLoader* BufferedDataSource::CreateLoader( 525 BufferedResourceLoader* BufferedDataSource::CreateResourceLoader(
487 int64 first_byte_position, int64 last_byte_position) { 526 int64 first_byte_position, int64 last_byte_position) {
488 DCHECK(MessageLoop::current() == render_loop_); 527 DCHECK(MessageLoop::current() == render_loop_);
489 528
490 return new BufferedResourceLoader(bridge_factory_.get(), url_, 529 return new BufferedResourceLoader(bridge_factory_.get(), url_,
491 first_byte_position, 530 first_byte_position,
492 last_byte_position); 531 last_byte_position);
493 } 532 }
494 533
495 // This method simply returns kTimeoutMilliseconds. The purpose of this 534 // This method simply returns kTimeoutMilliseconds. The purpose of this
496 // method is to be overidded so as to provide a different timeout value 535 // method is to be overidded so as to provide a different timeout value
(...skipping 26 matching lines...) Expand all
523 media_format_.SetAsString(media::MediaFormat::kURL, url); 562 media_format_.SetAsString(media::MediaFormat::kURL, url);
524 563
525 // Post a task to complete the initialization task. 564 // Post a task to complete the initialization task.
526 render_loop_->PostTask(FROM_HERE, 565 render_loop_->PostTask(FROM_HERE,
527 NewRunnableMethod(this, &BufferedDataSource::InitializeTask)); 566 NewRunnableMethod(this, &BufferedDataSource::InitializeTask));
528 } 567 }
529 568
530 void BufferedDataSource::Stop() { 569 void BufferedDataSource::Stop() {
531 { 570 {
532 AutoLock auto_lock(lock_); 571 AutoLock auto_lock(lock_);
533 stopped_ = true; 572 stop_signal_received_ = true;
534 } 573 }
535 render_loop_->PostTask(FROM_HERE, 574 render_loop_->PostTask(FROM_HERE,
536 NewRunnableMethod(this, &BufferedDataSource::StopTask)); 575 NewRunnableMethod(this, &BufferedDataSource::StopTask));
537 } 576 }
538 577
539 ///////////////////////////////////////////////////////////////////////////// 578 /////////////////////////////////////////////////////////////////////////////
540 // BufferedDataSource, media::DataSource implementation 579 // BufferedDataSource, media::DataSource implementation
541 void BufferedDataSource::Read(int64 position, size_t size, 580 void BufferedDataSource::Read(int64 position, size_t size, uint8* data,
542 uint8* data,
543 media::DataSource::ReadCallback* read_callback) { 581 media::DataSource::ReadCallback* read_callback) {
544 render_loop_->PostTask(FROM_HERE, 582 render_loop_->PostTask(FROM_HERE,
545 NewRunnableMethod(this, &BufferedDataSource::ReadTask, 583 NewRunnableMethod(this, &BufferedDataSource::ReadTask,
546 position, static_cast<int>(size), data, read_callback)); 584 position, static_cast<int>(size), data, read_callback));
547 } 585 }
548 586
549 bool BufferedDataSource::GetSize(int64* size_out) { 587 bool BufferedDataSource::GetSize(int64* size_out) {
550 if (total_bytes_ != kPositionNotSpecified) { 588 if (total_bytes_ != kPositionNotSpecified) {
551 *size_out = total_bytes_; 589 *size_out = total_bytes_;
552 return true; 590 return true;
553 } 591 }
554 *size_out = 0; 592 *size_out = 0;
555 return false; 593 return false;
556 } 594 }
557 595
558 bool BufferedDataSource::IsStreaming() { 596 bool BufferedDataSource::IsStreaming() {
559 return streaming_; 597 return streaming_;
560 } 598 }
561 599
562 ///////////////////////////////////////////////////////////////////////////// 600 /////////////////////////////////////////////////////////////////////////////
563 // BufferedDataSource, render thread tasks 601 // BufferedDataSource, render thread tasks
564 void BufferedDataSource::InitializeTask() { 602 void BufferedDataSource::InitializeTask() {
565 DCHECK(MessageLoop::current() == render_loop_); 603 DCHECK(MessageLoop::current() == render_loop_);
566 DCHECK(!loader_.get()); 604 DCHECK(!loader_.get());
605 DCHECK(!stopped_on_render_loop_);
567 606
568 // Kick starts the watch dog task that will handle connection timeout. 607 // Kick starts the watch dog task that will handle connection timeout.
569 // We run the watch dog 2 times faster the actual timeout so as to catch 608 // We run the watch dog 2 times faster the actual timeout so as to catch
570 // the timeout more accurately. 609 // the timeout more accurately.
571 watch_dog_timer_.Start( 610 watch_dog_timer_.Start(
572 GetTimeoutMilliseconds() / 2, 611 GetTimeoutMilliseconds() / 2,
573 this, 612 this,
574 &BufferedDataSource::WatchDogTask); 613 &BufferedDataSource::WatchDogTask);
575 614
576 if (IsHttpProtocol(url_)) { 615 if (IsHttpProtocol(url_)) {
577 // Fetch only first 1024 bytes as this usually covers the header portion 616 // Fetch only first 1024 bytes as this usually covers the header portion
578 // of a media file that gives enough information about the codecs, etc. 617 // of a media file that gives enough information about the codecs, etc.
579 // This also serve as a probe to determine server capability to serve 618 // This also serve as a probe to determine server capability to serve
580 // range request. 619 // range request.
581 // TODO(hclam): Do some experiments for the best approach. 620 // TODO(hclam): Do some experiments for the best approach.
582 loader_ = CreateLoader(0, 1024); 621 loader_ = CreateResourceLoader(0, 1024);
583 loader_->Start( 622 loader_->Start(
584 NewCallback(this, 623 NewCallback(this, &BufferedDataSource::HttpInitialStartCallback),
585 &BufferedDataSource::HttpInitialStartCallback)); 624 NewCallback(this, &BufferedDataSource::NetworkEventCallback));
586 } else { 625 } else {
587 // For all other protocols, assume they support range request. We fetch 626 // For all other protocols, assume they support range request. We fetch
588 // the full range of the resource to obtain the instance size because 627 // the full range of the resource to obtain the instance size because
589 // we won't be served HTTP headers. 628 // we won't be served HTTP headers.
590 loader_ = CreateLoader(-1, -1); 629 loader_ = CreateResourceLoader(-1, -1);
591 loader_->Start( 630 loader_->Start(
592 NewCallback(this, 631 NewCallback(this, &BufferedDataSource::NonHttpInitialStartCallback),
593 &BufferedDataSource::NonHttpInitialStartCallback)); 632 NewCallback(this, &BufferedDataSource::NetworkEventCallback));
594 } 633 }
595 } 634 }
596 635
597 void BufferedDataSource::ReadTask( 636 void BufferedDataSource::ReadTask(
598 int64 position, int read_size, uint8* buffer, 637 int64 position, int read_size, uint8* buffer,
599 media::DataSource::ReadCallback* read_callback) { 638 media::DataSource::ReadCallback* read_callback) {
600 DCHECK(MessageLoop::current() == render_loop_); 639 DCHECK(MessageLoop::current() == render_loop_);
601 640
602 // If StopTask() was executed we should return immediately. We check this 641 // If StopTask() was executed we should return immediately. We check this
603 // variable to prevent doing any actual work after clean up was done. We do 642 // variable to prevent doing any actual work after clean up was done. We do
604 // not check |stopped_| because anything use of it has to be within |lock_| 643 // not check |stop_signal_received_| because anything use of it has to be
605 // which is not desirable. 644 // within |lock_| which is not desirable.
606 if (stop_task_finished_) 645 if (stopped_on_render_loop_)
607 return; 646 return;
608 647
609 DCHECK(!read_callback_.get()); 648 DCHECK(!read_callback_.get());
610 DCHECK(read_callback); 649 DCHECK(read_callback);
611 650
612 // Saves the read parameters. 651 // Saves the read parameters.
613 read_position_ = position; 652 read_position_ = position;
614 read_size_ = read_size; 653 read_size_ = read_size;
615 read_callback_.reset(read_callback); 654 read_callback_.reset(read_callback);
616 read_buffer_ = buffer; 655 read_buffer_ = buffer;
617 read_submitted_time_ = base::Time::Now(); 656 read_submitted_time_ = base::Time::Now();
618 read_attempts_ = 0; 657 read_attempts_ = 0;
619 658
620 // Call to read internal to perform the actual read. 659 // Call to read internal to perform the actual read.
621 ReadInternal(); 660 ReadInternal();
622 } 661 }
623 662
624 void BufferedDataSource::StopTask() { 663 void BufferedDataSource::StopTask() {
625 DCHECK(MessageLoop::current() == render_loop_); 664 DCHECK(MessageLoop::current() == render_loop_);
665 DCHECK(!stopped_on_render_loop_);
626 666
627 // Stop the watch dog. 667 // Stop the watch dog.
628 watch_dog_timer_.Stop(); 668 watch_dog_timer_.Stop();
629 669
630 // We just need to stop the loader, so it stops activity. 670 // We just need to stop the loader, so it stops activity.
631 if (loader_.get()) 671 if (loader_.get())
632 loader_->Stop(); 672 loader_->Stop();
633 673
634 // Reset the parameters of the current read request. 674 // Reset the parameters of the current read request.
635 read_callback_.reset(); 675 read_callback_.reset();
636 read_position_ = 0; 676 read_position_ = 0;
637 read_size_ = 0; 677 read_size_ = 0;
638 read_buffer_ = 0; 678 read_buffer_ = 0;
639 read_submitted_time_ = base::Time(); 679 read_submitted_time_ = base::Time();
640 read_attempts_ = 0; 680 read_attempts_ = 0;
641 681
642 // Signal that stop task has finished execution. 682 // Signal that stop task has finished execution.
643 stop_task_finished_ = true; 683 stopped_on_render_loop_ = true;
644 } 684 }
645 685
646 void BufferedDataSource::SwapLoaderTask( 686 void BufferedDataSource::RestartLoadingTask() {
647 scoped_refptr<BufferedResourceLoader> loader) {
648 DCHECK(MessageLoop::current() == render_loop_); 687 DCHECK(MessageLoop::current() == render_loop_);
649 DCHECK(loader);
650 688
651 loader_ = loader; 689 // This variable is set in StopTask(). We check this and do an early return.
652 loader_->Start(NewCallback(this, 690 // The sequence of actions which enable this conditions is:
653 &BufferedDataSource::PartialReadStartCallback)); 691 // 1. Stop() is called from the pipeline.
692 // 2. ReadCallback() is called from the resource loader.
693 // 3. StopTask() is executed.
694 // 4. RestartLoadingTask() is executed.
695 if (stopped_on_render_loop_)
696 return;
697
698 // If there's no outstanding read then return early.
699 if (!read_callback_.get())
700 return;
701
702 loader_ = CreateResourceLoader(read_position_, -1);
703 loader_->Start(
704 NewCallback(this, &BufferedDataSource::PartialReadStartCallback),
705 NewCallback(this, &BufferedDataSource::NetworkEventCallback));
654 } 706 }
655 707
656 void BufferedDataSource::WatchDogTask() { 708 void BufferedDataSource::WatchDogTask() {
657 DCHECK(MessageLoop::current() == render_loop_); 709 DCHECK(MessageLoop::current() == render_loop_);
710 DCHECK(!stopped_on_render_loop_);
658 711
659 // We only care if there is an active read request. 712 // We only care if there is an active read request.
660 if (!read_callback_.get()) 713 if (!read_callback_.get())
661 return; 714 return;
662 715
663 DCHECK(loader_.get()); 716 DCHECK(loader_.get());
664 base::TimeDelta delta = base::Time::Now() - read_submitted_time_; 717 base::TimeDelta delta = base::Time::Now() - read_submitted_time_;
665 if (delta < GetTimeoutMilliseconds()) 718 if (delta < GetTimeoutMilliseconds())
666 return; 719 return;
667 720
668 // TODO(hclam): Maybe raise an error here. But if an error is reported 721 // TODO(hclam): Maybe raise an error here. But if an error is reported
669 // the whole pipeline may get destroyed... 722 // the whole pipeline may get destroyed...
670 if (read_attempts_ >= kReadTrials) 723 if (read_attempts_ >= kReadTrials)
671 return; 724 return;
672 725
673 ++read_attempts_; 726 ++read_attempts_;
674 read_submitted_time_ = base::Time::Now(); 727 read_submitted_time_ = base::Time::Now();
675 728
676 // Stops the current loader and swap in a new resource loader and 729 // Stops the current loader and creates a new resource loader and
677 // retry the request. 730 // retry the request.
678 loader_->Stop(); 731 loader_->Stop();
679 SwapLoaderTask(CreateLoader(read_position_, -1)); 732 loader_ = CreateResourceLoader(read_position_, -1);
733 loader_->Start(
734 NewCallback(this, &BufferedDataSource::PartialReadStartCallback),
735 NewCallback(this, &BufferedDataSource::NetworkEventCallback));
680 } 736 }
681 737
682 // This method is the place where actual read happens, |loader_| must be valid 738 // This method is the place where actual read happens, |loader_| must be valid
683 // prior to make this method call. 739 // prior to make this method call.
684 void BufferedDataSource::ReadInternal() { 740 void BufferedDataSource::ReadInternal() {
685 DCHECK(MessageLoop::current() == render_loop_); 741 DCHECK(MessageLoop::current() == render_loop_);
686 DCHECK(loader_.get()); 742 DCHECK(loader_.get());
687 743
688 // First we prepare the intermediate read buffer for BufferedResourceLoader 744 // First we prepare the intermediate read buffer for BufferedResourceLoader
689 // to write to. 745 // to write to.
690 if (read_size_ > intermediate_read_buffer_size_) { 746 if (read_size_ > intermediate_read_buffer_size_) {
691 intermediate_read_buffer_.reset(new uint8[read_size_]); 747 intermediate_read_buffer_.reset(new uint8[read_size_]);
692 } 748 }
693 749
694 // Perform the actual read with BufferedResourceLoader. 750 // Perform the actual read with BufferedResourceLoader.
695 loader_->Read(read_position_, read_size_, intermediate_read_buffer_.get(), 751 loader_->Read(read_position_, read_size_, intermediate_read_buffer_.get(),
696 NewCallback(this, &BufferedDataSource::ReadCallback)); 752 NewCallback(this, &BufferedDataSource::ReadCallback));
697 } 753 }
698 754
699 // Method to report the results of the current read request. Also reset all 755 // Method to report the results of the current read request. Also reset all
700 // the read parameters. 756 // the read parameters.
701 void BufferedDataSource::DoneRead(int error) { 757 void BufferedDataSource::DoneRead_Locked(int error) {
702 DCHECK(MessageLoop::current() == render_loop_); 758 DCHECK(MessageLoop::current() == render_loop_);
759 DCHECK(read_callback_.get());
703 lock_.AssertAcquired(); 760 lock_.AssertAcquired();
704 761
705 if (error >= 0) { 762 if (error >= 0) {
706 read_callback_->RunWithParams(Tuple1<size_t>(error)); 763 read_callback_->RunWithParams(Tuple1<size_t>(error));
707 } else { 764 } else {
708 read_callback_->RunWithParams( 765 read_callback_->RunWithParams(
709 Tuple1<size_t>(static_cast<size_t>(media::DataSource::kReadError))); 766 Tuple1<size_t>(static_cast<size_t>(media::DataSource::kReadError)));
710 } 767 }
711 768
712 read_callback_.reset(); 769 read_callback_.reset();
713 read_position_ = 0; 770 read_position_ = 0;
714 read_size_ = 0; 771 read_size_ = 0;
715 read_buffer_ = 0; 772 read_buffer_ = 0;
716 } 773 }
717 774
718 void BufferedDataSource::DoneInitialization() { 775 void BufferedDataSource::DoneInitialization_Locked() {
776 DCHECK(MessageLoop::current() == render_loop_);
719 DCHECK(initialize_callback_.get()); 777 DCHECK(initialize_callback_.get());
720 lock_.AssertAcquired(); 778 lock_.AssertAcquired();
721 779
722 initialize_callback_->Run(); 780 initialize_callback_->Run();
723 initialize_callback_.reset(); 781 initialize_callback_.reset();
724 } 782 }
725 783
726 ///////////////////////////////////////////////////////////////////////////// 784 /////////////////////////////////////////////////////////////////////////////
727 // BufferedDataSource, callback methods. 785 // BufferedDataSource, callback methods.
728 // These methods are called on the render thread for the events reported by 786 // These methods are called on the render thread for the events reported by
729 // BufferedResourceLoader. 787 // BufferedResourceLoader.
730 void BufferedDataSource::HttpInitialStartCallback(int error) { 788 void BufferedDataSource::HttpInitialStartCallback(int error) {
731 DCHECK(MessageLoop::current() == render_loop_); 789 DCHECK(MessageLoop::current() == render_loop_);
790 DCHECK(loader_.get());
791
792 int64 instance_size = loader_->instance_size();
793 bool partial_response = loader_->partial_response();
794 bool success = error == net::OK;
795
796 if (success) {
797 // TODO(hclam): Needs more thinking about supporting servers without range
798 // request or their partial response is not complete.
799 total_bytes_ = instance_size;
800 loaded_ = false;
801 streaming_ = (instance_size == kPositionNotSpecified) || !partial_response;
802 } else {
803 // TODO(hclam): In case of failure, we can retry several times.
804 loader_->Stop();
805 }
732 806
733 // We need to prevent calling to filter host and running the callback if 807 // We need to prevent calling to filter host and running the callback if
734 // we have received the stop signal. We need to lock down the whole callback 808 // we have received the stop signal. We need to lock down the whole callback
735 // method to prevent bad things from happening. The reason behind this is 809 // method to prevent bad things from happening. The reason behind this is
736 // that we cannot guarantee tasks on render thread have completely stopped 810 // that we cannot guarantee tasks on render thread have completely stopped
737 // when we receive the Stop() method call. The only way to solve this is to 811 // when we receive the Stop() method call. The only way to solve this is to
738 // let tasks on render thread to run but make sure they don't call outside 812 // let tasks on render thread to run but make sure they don't call outside
739 // this object when Stop() method is ever called. Locking this method is safe 813 // this object when Stop() method is ever called. Locking this method is safe
740 // because |lock_| is only acquired in tasks on render thread. 814 // because |lock_| is only acquired in tasks on render thread.
741 AutoLock auto_lock(lock_); 815 AutoLock auto_lock(lock_);
742 if (stopped_) 816 if (stop_signal_received_)
743 return; 817 return;
744 818
745 if (error != net::OK) { 819 if (!success) {
746 // TODO(hclam): In case of failure, we can retry several times.
747 host()->SetError(media::PIPELINE_ERROR_NETWORK); 820 host()->SetError(media::PIPELINE_ERROR_NETWORK);
748 DCHECK(loader_.get()); 821 DoneInitialization_Locked();
749 loader_->Stop();
750 DoneInitialization();
751 return; 822 return;
752 } 823 }
753 824
754 // TODO(hclam): Needs more thinking about supporting servers without range 825 if (streaming_) {
755 // request or their partial response is not complete. 826 // If the server didn't reply with an instance size, it is likely this
756 total_bytes_ = loader_->instance_size(); 827 // is a streaming response.
757 if (total_bytes_ >= 0 && loader_->partial_response()) { 828 host()->SetStreaming(true);
829 } else {
758 // This value governs the range that we can seek to. 830 // This value governs the range that we can seek to.
759 // TODO(hclam): Report the correct value of buffered bytes. 831 // TODO(hclam): Report the correct value of buffered bytes.
760 host()->SetTotalBytes(total_bytes_); 832 host()->SetTotalBytes(total_bytes_);
761 host()->SetBufferedBytes(total_bytes_); 833 host()->SetBufferedBytes(0);
762 } else {
763 // If the server didn't reply with an instance size, it is likely this
764 // is a streaming response.
765 streaming_ = true;
766 host()->SetStreaming(true);
767 } 834 }
768 835
769 // Currently, only files can be used reliably w/o a network. 836 // Currently, only files can be used reliably w/o a network.
770 host()->SetLoaded(false); 837 host()->SetLoaded(false);
771 DoneInitialization(); 838 DoneInitialization_Locked();
772 } 839 }
773 840
774 void BufferedDataSource::NonHttpInitialStartCallback(int error) { 841 void BufferedDataSource::NonHttpInitialStartCallback(int error) {
775 DCHECK(MessageLoop::current() == render_loop_); 842 DCHECK(MessageLoop::current() == render_loop_);
843 DCHECK(loader_.get());
844
845 int64 instance_size = loader_->instance_size();
846 bool success = error == net::OK && instance_size != kPositionNotSpecified;
847
848 if (success) {
849 total_bytes_ = instance_size;
850 loaded_ = true;
851 } else {
852 loader_->Stop();
853 }
776 854
777 // We need to prevent calling to filter host and running the callback if 855 // We need to prevent calling to filter host and running the callback if
778 // we have received the stop signal. We need to lock down the whole callback 856 // we have received the stop signal. We need to lock down the whole callback
779 // method to prevent bad things from happening. The reason behind this is 857 // method to prevent bad things from happening. The reason behind this is
780 // that we cannot guarantee tasks on render thread have completely stopped 858 // that we cannot guarantee tasks on render thread have completely stopped
781 // when we receive the Stop() method call. The only way to solve this is to 859 // when we receive the Stop() method call. The only way to solve this is to
782 // let tasks on render thread to run but make sure they don't call outside 860 // let tasks on render thread to run but make sure they don't call outside
783 // this object when Stop() method is ever called. Locking this method is safe 861 // this object when Stop() method is ever called. Locking this method is safe
784 // because |lock_| is only acquired in tasks on render thread. 862 // because |lock_| is only acquired in tasks on render thread.
785 AutoLock auto_lock(lock_); 863 AutoLock auto_lock(lock_);
786 if (stopped_) 864 if (stop_signal_received_)
787 return; 865 return;
788 866
789 DCHECK(loader_.get()); 867 if (success) {
790 868 host()->SetTotalBytes(total_bytes_);
791 if (error != net::OK || loader_->instance_size() == kPositionNotSpecified) { 869 host()->SetBufferedBytes(total_bytes_);
870 host()->SetLoaded(loaded_);
871 } else {
792 host()->SetError(media::PIPELINE_ERROR_NETWORK); 872 host()->SetError(media::PIPELINE_ERROR_NETWORK);
793 loader_->Stop();
794 DoneInitialization();
795 return;
796 } 873 }
797 874 DoneInitialization_Locked();
798 total_bytes_ = loader_->instance_size();
799 host()->SetTotalBytes(total_bytes_);
800 host()->SetBufferedBytes(total_bytes_);
801 host()->SetLoaded(true);
802 DoneInitialization();
803 } 875 }
804 876
805 void BufferedDataSource::PartialReadStartCallback(int error) { 877 void BufferedDataSource::PartialReadStartCallback(int error) {
806 DCHECK(MessageLoop::current() == render_loop_); 878 DCHECK(MessageLoop::current() == render_loop_);
807 DCHECK(loader_.get()); 879 DCHECK(loader_.get());
808 880
809 // This callback method is invoked after we have verified the server has 881 // This callback method is invoked after we have verified the server has
810 // range request capability, so as a safety guard verify again the response 882 // range request capability, so as a safety guard verify again the response
811 // is partial. 883 // is partial.
812 if (error == net::OK && loader_->partial_response()) { 884 if (error == net::OK && loader_->partial_response()) {
813 // Once the range request has started successfully, we can proceed with 885 // Once the range request has started successfully, we can proceed with
814 // reading from it. 886 // reading from it.
815 ReadInternal(); 887 ReadInternal();
816 } else { 888 return;
817 loader_->Stop(); 889 }
818 890
819 // We need to prevent calling to filter host and running the callback if 891 // Stop the resource loader since we have received an error.
820 // we have received the stop signal. We need to lock down the whole callback 892 loader_->Stop();
821 // method to prevent bad things from happening. The reason behind this is 893
822 // that we cannot guarantee tasks on render thread have completely stopped 894 // We need to prevent calling to filter host and running the callback if
823 // when we receive the Stop() method call. So only way to solve this is to 895 // we have received the stop signal. We need to lock down the whole callback
824 // let tasks on render thread to run but make sure they don't call outside 896 // method to prevent bad things from happening. The reason behind this is
825 // this object when Stop() method is ever called. Locking this method is 897 // that we cannot guarantee tasks on render thread have completely stopped
826 // safe because |lock_| is only acquired in tasks on render thread. 898 // when we receive the Stop() method call. So only way to solve this is to
827 AutoLock auto_lock(lock_); 899 // let tasks on render thread to run but make sure they don't call outside
828 if (stopped_) 900 // this object when Stop() method is ever called. Locking this method is
829 return; 901 // safe because |lock_| is only acquired in tasks on render thread.
830 DoneRead(net::ERR_INVALID_RESPONSE); 902 AutoLock auto_lock(lock_);
831 } 903 if (stop_signal_received_)
904 return;
905 DoneRead_Locked(net::ERR_INVALID_RESPONSE);
832 } 906 }
833 907
834 void BufferedDataSource::ReadCallback(int error) { 908 void BufferedDataSource::ReadCallback(int error) {
835 DCHECK(MessageLoop::current() == render_loop_); 909 DCHECK(MessageLoop::current() == render_loop_);
836 910
911 if (error < 0) {
912 DCHECK(loader_.get());
913
914 // Stop the resource load if it failed.
915 loader_->Stop();
916
917 if (error == net::ERR_CACHE_MISS) {
918 render_loop_->PostTask(FROM_HERE,
919 NewRunnableMethod(this, &BufferedDataSource::RestartLoadingTask));
920 return;
921 }
922 }
923
837 // We need to prevent calling to filter host and running the callback if 924 // We need to prevent calling to filter host and running the callback if
838 // we have received the stop signal. We need to lock down the whole callback 925 // we have received the stop signal. We need to lock down the whole callback
839 // method to prevent bad things from happening. The reason behind this is 926 // method to prevent bad things from happening. The reason behind this is
840 // that we cannot guarantee tasks on render thread have completely stopped 927 // that we cannot guarantee tasks on render thread have completely stopped
841 // when we receive the Stop() method call. So only way to solve this is to 928 // when we receive the Stop() method call. So only way to solve this is to
842 // let tasks on render thread to run but make sure they don't call outside 929 // let tasks on render thread to run but make sure they don't call outside
843 // this object when Stop() method is ever called. Locking this method is safe 930 // this object when Stop() method is ever called. Locking this method is safe
844 // because |lock_| is only acquired in tasks on render thread. 931 // because |lock_| is only acquired in tasks on render thread.
845 AutoLock auto_lock(lock_); 932 AutoLock auto_lock(lock_);
846 if (stopped_) 933 if (stop_signal_received_)
847 return; 934 return;
848 935
849 DCHECK(loader_.get()); 936 if (error > 0) {
850 DCHECK(read_callback_.get());
851
852 if (error >= 0) {
853 // If a position error code is received, read was successful. So copy 937 // If a position error code is received, read was successful. So copy
854 // from intermediate read buffer to the target read buffer. 938 // from intermediate read buffer to the target read buffer.
855 memcpy(read_buffer_, intermediate_read_buffer_.get(), error); 939 memcpy(read_buffer_, intermediate_read_buffer_.get(), error);
856 DoneRead(error); 940 }
857 } else if (error == net::ERR_CACHE_MISS) { 941 DoneRead_Locked(error);
858 // If the current loader cannot serve this read request, we need to create 942 }
859 // a new one.
860 // TODO(hclam): we need to count how many times it failed to prevent
861 // excessive trials.
862 943
863 // Stops the current resource loader. 944 void BufferedDataSource::NetworkEventCallback() {
864 loader_->Stop(); 945 DCHECK(MessageLoop::current() == render_loop_);
946 DCHECK(loader_.get());
865 947
866 // Since this method is called from the current buffered resource loader, 948 // In case of non-HTTP request we don't need to report network events,
867 // we cannot delete it. So we need to post a task to swap in a new 949 // so return immediately.
868 // resource loader and starts it. 950 if (loaded_)
869 render_loop_->PostTask(FROM_HERE, 951 return;
870 NewRunnableMethod(this, &BufferedDataSource::SwapLoaderTask, 952
871 CreateLoader(read_position_, -1))); 953 bool network_activity = loader_->network_activity();
872 } else { 954 int64 buffered_last_byte_position = loader_->GetBufferedLastBytePosition();
873 loader_->Stop(); 955
874 DoneRead(error); 956 // If we get an unspecified value, return immediately.
957 if (buffered_last_byte_position == kPositionNotSpecified)
958 return;
959
960 // We need to prevent calling to filter host and running the callback if
961 // we have received the stop signal. We need to lock down the whole callback
962 // method to prevent bad things from happening. The reason behind this is
963 // that we cannot guarantee tasks on render thread have completely stopped
964 // when we receive the Stop() method call. So only way to solve this is to
965 // let tasks on render thread to run but make sure they don't call outside
966 // this object when Stop() method is ever called. Locking this method is safe
967 // because |lock_| is only acquired in tasks on render thread.
968 AutoLock auto_lock(lock_);
969 if (stop_signal_received_)
970 return;
971
972 if (network_activity != network_activity_) {
973 network_activity_ = network_activity;
974 host()->SetNetworkActivity(network_activity);
875 } 975 }
976 host()->SetBufferedBytes(buffered_last_byte_position + 1);
876 } 977 }
877 978
878 } // namespace webkit_glue 979 } // namespace webkit_glue
OLDNEW
« no previous file with comments | « webkit/glue/media/buffered_data_source.h ('k') | webkit/glue/media/buffered_data_source_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698