Commit 96fe0aff authored by scherkus@chromium.org's avatar scherkus@chromium.org

Collapse HTTP and non-HTTP codepaths into single methods.

Duplicating ~100 lines of code for the ~5 lines of code that are different isn't worth it.

BUG=none
TEST=none

Review URL: https://chromiumcodereview.appspot.com/10735016

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146242 0039d316-1c4b-4281-b951-d872f2087c98
parent 2ffca60d
...@@ -26,13 +26,6 @@ const int kNumCacheMissRetries = 3; ...@@ -26,13 +26,6 @@ const int kNumCacheMissRetries = 3;
namespace webkit_media { namespace webkit_media {
// Non-HTTP resources are assumed to be fully loaded so we ignore any
// loading/progress related callbacks.
static void NonHttpLoadingStateChangedCallback(
BufferedResourceLoader::LoadingState) {
}
static void NonHttpProgressCallback(int64) {}
BufferedDataSource::BufferedDataSource( BufferedDataSource::BufferedDataSource(
MessageLoop* render_loop, MessageLoop* render_loop,
WebFrame* frame, WebFrame* frame,
...@@ -109,23 +102,19 @@ void BufferedDataSource::Initialize( ...@@ -109,23 +102,19 @@ void BufferedDataSource::Initialize(
// Do an unbounded range request starting at the beginning. If the server // Do an unbounded range request starting at the beginning. If the server
// responds with 200 instead of 206 we'll fall back into a streaming mode. // responds with 200 instead of 206 we'll fall back into a streaming mode.
loader_.reset(CreateResourceLoader(0, kPositionNotSpecified)); loader_.reset(CreateResourceLoader(0, kPositionNotSpecified));
loader_->Start( } else {
base::Bind(&BufferedDataSource::HttpInitialStartCallback, this), // For all other protocols, assume they support range request. We fetch
base::Bind(&BufferedDataSource::HttpLoadingStateChangedCallback, this), // the full range of the resource to obtain the instance size because
base::Bind(&BufferedDataSource::HttpProgressCallback, this), // we won't be served HTTP headers.
frame_); loader_.reset(CreateResourceLoader(kPositionNotSpecified,
return; kPositionNotSpecified));
assume_fully_buffered_ = true;
} }
// For all other protocols, assume they support range request. We fetch
// the full range of the resource to obtain the instance size because
// we won't be served HTTP headers.
loader_.reset(CreateResourceLoader(kPositionNotSpecified,
kPositionNotSpecified));
loader_->Start( loader_->Start(
base::Bind(&BufferedDataSource::NonHttpInitialStartCallback, this), base::Bind(&BufferedDataSource::StartCallback, this),
base::Bind(&NonHttpLoadingStateChangedCallback), base::Bind(&BufferedDataSource::LoadingStateChangedCallback, this),
base::Bind(&NonHttpProgressCallback), base::Bind(&BufferedDataSource::ProgressCallback, this),
frame_); frame_);
} }
...@@ -278,21 +267,12 @@ void BufferedDataSource::RestartLoadingTask() { ...@@ -278,21 +267,12 @@ void BufferedDataSource::RestartLoadingTask() {
} }
// Start reading from where we last left off until the end of the resource. // Start reading from where we last left off until the end of the resource.
loader_.reset( loader_.reset(CreateResourceLoader(last_read_start_, kPositionNotSpecified));
CreateResourceLoader(last_read_start_, kPositionNotSpecified)); loader_->Start(
if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { base::Bind(&BufferedDataSource::PartialReadStartCallback, this),
loader_->Start( base::Bind(&BufferedDataSource::LoadingStateChangedCallback, this),
base::Bind(&BufferedDataSource::PartialReadStartCallback, this), base::Bind(&BufferedDataSource::ProgressCallback, this),
base::Bind(&BufferedDataSource::HttpLoadingStateChangedCallback, this), frame_);
base::Bind(&BufferedDataSource::HttpProgressCallback, this),
frame_);
} else {
loader_->Start(
base::Bind(&BufferedDataSource::PartialReadStartCallback, this),
base::Bind(&NonHttpLoadingStateChangedCallback),
base::Bind(&NonHttpProgressCallback),
frame_);
}
} }
void BufferedDataSource::SetPlaybackRateTask(float playback_rate) { void BufferedDataSource::SetPlaybackRateTask(float playback_rate) {
...@@ -375,7 +355,7 @@ void BufferedDataSource::DoneInitialization_Locked( ...@@ -375,7 +355,7 @@ void BufferedDataSource::DoneInitialization_Locked(
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// BufferedResourceLoader callback methods. // BufferedResourceLoader callback methods.
void BufferedDataSource::HttpInitialStartCallback( void BufferedDataSource::StartCallback(
BufferedResourceLoader::Status status) { BufferedResourceLoader::Status status) {
DCHECK(MessageLoop::current() == render_loop_); DCHECK(MessageLoop::current() == render_loop_);
DCHECK(loader_.get()); DCHECK(loader_.get());
...@@ -390,90 +370,26 @@ void BufferedDataSource::HttpInitialStartCallback( ...@@ -390,90 +370,26 @@ void BufferedDataSource::HttpInitialStartCallback(
return; return;
} }
bool success = status == BufferedResourceLoader::kOk; // All responses must be successful. Resources that are assumed to be fully
if (success) { // buffered must have a known content length.
// TODO(hclam): Needs more thinking about supporting servers without range
// request or their partial response is not complete.
total_bytes_ = loader_->instance_size();
streaming_ = (total_bytes_ == kPositionNotSpecified) ||
!loader_->range_supported();
} else {
// TODO(hclam): In case of failure, we can retry several times.
loader_->Stop();
}
// Reference to prevent destruction while inside the |initialize_cb_|
// call. This is a temporary fix to prevent crashes caused by holding the
// lock and running the destructor.
// TODO: Review locking in this class and figure out a way to run the callback
// w/o the lock.
scoped_refptr<BufferedDataSource> destruction_guard(this);
{
// We need to prevent calling to filter host and running the callback if
// we have received the stop signal. We need to lock down the whole callback
// method to prevent bad things from happening. The reason behind this is
// that we cannot guarantee tasks on render thread have completely stopped
// when we receive the Stop() method call. The only way to solve this is to
// let tasks on render thread to run but make sure they don't call outside
// this object when Stop() method is ever called. Locking this method is
// safe because |lock_| is only acquired in tasks on render thread.
base::AutoLock auto_lock(lock_);
if (stop_signal_received_)
return;
if (!success) {
DoneInitialization_Locked(media::PIPELINE_ERROR_NETWORK);
return;
}
UpdateHostState_Locked();
DoneInitialization_Locked(media::PIPELINE_OK);
}
}
void BufferedDataSource::NonHttpInitialStartCallback(
BufferedResourceLoader::Status status) {
DCHECK(MessageLoop::current() == render_loop_);
DCHECK(loader_.get());
bool initialize_cb_is_null = false;
{
base::AutoLock auto_lock(lock_);
initialize_cb_is_null = initialize_cb_.is_null();
}
if (initialize_cb_is_null) {
loader_->Stop();
return;
}
int64 instance_size = loader_->instance_size();
bool success = status == BufferedResourceLoader::kOk && bool success = status == BufferedResourceLoader::kOk &&
instance_size != kPositionNotSpecified; (!assume_fully_buffered_ ||
loader_->instance_size() != kPositionNotSpecified);
if (success) { if (success) {
total_bytes_ = instance_size; total_bytes_ = loader_->instance_size();
assume_fully_buffered_ = true; streaming_ = !assume_fully_buffered_ &&
(total_bytes_ == kPositionNotSpecified || !loader_->range_supported());
} else { } else {
loader_->Stop(); loader_->Stop();
} }
// Reference to prevent destruction while inside the |initialize_cb_| // TODO(scherkus): we shouldn't have to lock to signal host(), see
// call. This is a temporary fix to prevent crashes caused by holding the // http://crbug.com/113712 for details.
// lock and running the destructor.
// TODO: Review locking in this class and figure out a way to run the callback
// w/o the lock.
scoped_refptr<BufferedDataSource> destruction_guard(this); scoped_refptr<BufferedDataSource> destruction_guard(this);
{ {
// We need to prevent calling to filter host and running the callback if
// we have received the stop signal. We need to lock down the whole callback
// method to prevent bad things from happening. The reason behind this is
// that we cannot guarantee tasks on render thread have completely stopped
// when we receive the Stop() method call. The only way to solve this is to
// let tasks on render thread to run but make sure they don't call outside
// this object when Stop() method is ever called. Locking this method is
// safe because |lock_| is only acquired in tasks on render thread.
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
if (stop_signal_received_ || initialize_cb_.is_null()) if (stop_signal_received_)
return; return;
if (!success) { if (!success) {
...@@ -501,14 +417,8 @@ void BufferedDataSource::PartialReadStartCallback( ...@@ -501,14 +417,8 @@ void BufferedDataSource::PartialReadStartCallback(
// Stop the resource loader since we have received an error. // Stop the resource loader since we have received an error.
loader_->Stop(); loader_->Stop();
// We need to prevent calling to filter host and running the callback if // TODO(scherkus): we shouldn't have to lock to signal host(), see
// we have received the stop signal. We need to lock down the whole callback // http://crbug.com/113712 for details.
// method to prevent bad things from happening. The reason behind this is
// that we cannot guarantee tasks on render thread have completely stopped
// when we receive the Stop() method call. So only way to solve this is to
// let tasks on render thread to run but make sure they don't call outside
// this object when Stop() method is ever called. Locking this method is
// safe because |lock_| is only acquired in tasks on render thread.
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
if (stop_signal_received_) if (stop_signal_received_)
return; return;
...@@ -559,10 +469,12 @@ void BufferedDataSource::ReadCallback( ...@@ -559,10 +469,12 @@ void BufferedDataSource::ReadCallback(
DoneRead_Locked(bytes_read); DoneRead_Locked(bytes_read);
} }
void BufferedDataSource::HttpLoadingStateChangedCallback( void BufferedDataSource::LoadingStateChangedCallback(
BufferedResourceLoader::LoadingState state) { BufferedResourceLoader::LoadingState state) {
DCHECK(MessageLoop::current() == render_loop_); DCHECK(MessageLoop::current() == render_loop_);
DCHECK(url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme));
if (assume_fully_buffered_)
return;
bool is_downloading_data; bool is_downloading_data;
switch (state) { switch (state) {
...@@ -587,9 +499,11 @@ void BufferedDataSource::HttpLoadingStateChangedCallback( ...@@ -587,9 +499,11 @@ void BufferedDataSource::HttpLoadingStateChangedCallback(
downloading_cb_.Run(is_downloading_data); downloading_cb_.Run(is_downloading_data);
} }
void BufferedDataSource::HttpProgressCallback(int64 position) { void BufferedDataSource::ProgressCallback(int64 position) {
DCHECK(MessageLoop::current() == render_loop_); DCHECK(MessageLoop::current() == render_loop_);
DCHECK(url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme));
if (assume_fully_buffered_)
return;
// TODO(scherkus): we shouldn't have to lock to signal host(), see // TODO(scherkus): we shouldn't have to lock to signal host(), see
// http://crbug.com/113712 for details. // http://crbug.com/113712 for details.
......
...@@ -123,29 +123,17 @@ class BufferedDataSource : public media::DataSource { ...@@ -123,29 +123,17 @@ class BufferedDataSource : public media::DataSource {
// Calls |initialize_cb_| and reset it. // Calls |initialize_cb_| and reset it.
void DoneInitialization_Locked(media::PipelineStatus status); void DoneInitialization_Locked(media::PipelineStatus status);
// Callback method for |loader_| if URL for the resource requested is using // BufferedResourceLoader::Start() callback for initial load.
// HTTP protocol. This method is called when response for initial request is void StartCallback(BufferedResourceLoader::Status status);
// received.
void HttpInitialStartCallback(BufferedResourceLoader::Status status); // BufferedResourceLoader::Start() callback for subsequent loads (i.e.,
// when accessing ranges that are outside initial buffered region).
// Callback method for |loader_| if URL for the resource requested is using
// a non-HTTP protocol, e.g. local files. This method is called when response
// for initial request is received.
void NonHttpInitialStartCallback(BufferedResourceLoader::Status status);
// Callback method to be passed to BufferedResourceLoader during range
// request. Once a resource request has started, this method will be called
// with the error code. This method will be executed on the thread
// BufferedResourceLoader lives, i.e. render thread.
void PartialReadStartCallback(BufferedResourceLoader::Status status); void PartialReadStartCallback(BufferedResourceLoader::Status status);
// Read callback for BufferedResourceLoader. // BufferedResourceLoader callbacks.
void ReadCallback(BufferedResourceLoader::Status status, int bytes_read); void ReadCallback(BufferedResourceLoader::Status status, int bytes_read);
void LoadingStateChangedCallback(BufferedResourceLoader::LoadingState state);
// Loading and progress callbacks for HTTP resources. void ProgressCallback(int64 position);
void HttpLoadingStateChangedCallback(
BufferedResourceLoader::LoadingState state);
void HttpProgressCallback(int64 position);
void UpdateHostState_Locked(); void UpdateHostState_Locked();
......
...@@ -465,6 +465,7 @@ TEST_F(BufferedDataSourceTest, File_Successful) { ...@@ -465,6 +465,7 @@ TEST_F(BufferedDataSourceTest, File_Successful) {
InitializeWithFileResponse(); InitializeWithFileResponse();
EXPECT_TRUE(data_source_->loading()); EXPECT_TRUE(data_source_->loading());
EXPECT_FALSE(data_source_->IsStreaming());
Stop(); Stop();
} }
......
...@@ -31,8 +31,10 @@ const char kHttpScheme[] = "http"; ...@@ -31,8 +31,10 @@ const char kHttpScheme[] = "http";
const char kHttpsScheme[] = "https"; const char kHttpsScheme[] = "https";
const char kDataScheme[] = "data"; const char kDataScheme[] = "data";
// Wraps a WebURLLoader to maintain an in-memory buffer of downloaded // BufferedResourceLoader is single threaded and must be accessed on the
// data according to the current defer strategy. // render thread. It wraps a WebURLLoader and does in-memory buffering,
// pausing resource loading when the in-memory buffer is full and resuming
// resource loading when there is available capacity.
class BufferedResourceLoader : public WebKit::WebURLLoaderClient { class BufferedResourceLoader : public WebKit::WebURLLoaderClient {
public: public:
// kNeverDefer - Aggresively buffer; never defer loading while paused. // kNeverDefer - Aggresively buffer; never defer loading while paused.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment