| Index: webkit/glue/media/buffered_data_source.cc
|
| diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc
|
| index 29c86ac8f07323ecfa554f83968c099fcb59cad2..75fbe5b99a1063bafa02d5de03a68583b0dc5829 100644
|
| --- a/webkit/glue/media/buffered_data_source.cc
|
| +++ b/webkit/glue/media/buffered_data_source.cc
|
| @@ -4,19 +4,33 @@
|
|
|
| #include "base/callback.h"
|
| #include "base/compiler_specific.h"
|
| +#include "base/format_macros.h"
|
| #include "base/message_loop.h"
|
| #include "base/process_util.h"
|
| #include "base/stl_util-inl.h"
|
| +#include "base/string_number_conversions.h"
|
| #include "base/string_util.h"
|
| #include "media/base/filter_host.h"
|
| #include "media/base/media_format.h"
|
| #include "net/base/load_flags.h"
|
| #include "net/base/net_errors.h"
|
| -#include "net/http/http_response_headers.h"
|
| +#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
|
| +#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h"
|
| +#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
|
| +#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
|
| #include "webkit/glue/media/buffered_data_source.h"
|
| +#include "webkit/glue/multipart_response_delegate.h"
|
| #include "webkit/glue/webkit_glue.h"
|
| #include "webkit/glue/webmediaplayer_impl.h"
|
|
|
| +using WebKit::WebFrame;
|
| +using WebKit::WebString;
|
| +using WebKit::WebURLError;
|
| +using WebKit::WebURLLoader;
|
| +using WebKit::WebURLRequest;
|
| +using WebKit::WebURLResponse;
|
| +using webkit_glue::MultipartResponseDelegate;
|
| +
|
| namespace {
|
|
|
| const char kHttpScheme[] = "http";
|
| @@ -70,10 +84,10 @@ bool IsDataProtocol(const GURL& url) {
|
| } // namespace
|
|
|
| namespace webkit_glue {
|
| +
|
| /////////////////////////////////////////////////////////////////////////////
|
| // BufferedResourceLoader
|
| BufferedResourceLoader::BufferedResourceLoader(
|
| - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory,
|
| const GURL& url,
|
| int64 first_byte_position,
|
| int64 last_byte_position)
|
| @@ -83,12 +97,10 @@ BufferedResourceLoader::BufferedResourceLoader(
|
| completed_(false),
|
| range_requested_(false),
|
| partial_response_(false),
|
| - bridge_factory_(bridge_factory),
|
| url_(url),
|
| first_byte_position_(first_byte_position),
|
| last_byte_position_(last_byte_position),
|
| start_callback_(NULL),
|
| - bridge_(NULL),
|
| offset_(0),
|
| content_length_(kPositionNotSpecified),
|
| instance_size_(kPositionNotSpecified),
|
| @@ -97,20 +109,24 @@ BufferedResourceLoader::BufferedResourceLoader(
|
| read_size_(0),
|
| read_buffer_(NULL),
|
| first_offset_(0),
|
| - last_offset_(0) {
|
| + last_offset_(0),
|
| + keep_test_loader_(false) {
|
| }
|
|
|
| BufferedResourceLoader::~BufferedResourceLoader() {
|
| + if (!completed_ && url_loader_.get())
|
| + url_loader_->cancel();
|
| }
|
|
|
| void BufferedResourceLoader::Start(net::CompletionCallback* start_callback,
|
| - NetworkEventCallback* event_callback) {
|
| + NetworkEventCallback* event_callback,
|
| + WebFrame* frame) {
|
| // Make sure we have not started.
|
| - DCHECK(!bridge_.get());
|
| DCHECK(!start_callback_.get());
|
| DCHECK(!event_callback_.get());
|
| DCHECK(start_callback);
|
| DCHECK(event_callback);
|
| + CHECK(frame);
|
|
|
| start_callback_.reset(start_callback);
|
| event_callback_.reset(event_callback);
|
| @@ -122,21 +138,26 @@ void BufferedResourceLoader::Start(net::CompletionCallback* start_callback,
|
| offset_ = first_byte_position_;
|
| }
|
|
|
| - // Creates the bridge on render thread since we can only access
|
| - // ResourceDispatcher on this thread.
|
| - bridge_.reset(
|
| - bridge_factory_->CreateBridge(
|
| - url_,
|
| - net::LOAD_NORMAL,
|
| - first_byte_position_,
|
| - last_byte_position_));
|
| -
|
| // Increment the reference count right before we start the request. This
|
| // reference will be release when this request has ended.
|
| AddRef();
|
|
|
| - // And start the resource loading.
|
| - bridge_->Start(this);
|
| + // Prepare the request.
|
| + WebURLRequest request(url_);
|
| + request.setHTTPHeaderField(WebString::fromUTF8("Range"),
|
| + WebString::fromUTF8(GenerateHeaders(
|
| + first_byte_position_,
|
| + last_byte_position_)));
|
| + frame->setReferrerForRequest(request, WebKit::WebURL());
|
| + // TODO(annacc): we should be using createAssociatedURLLoader() instead?
|
| + frame->dispatchWillSendRequest(request);
|
| +
|
| + // This flag is for unittests as we don't want to reset |url_loader|
|
| + if (!keep_test_loader_)
|
| + url_loader_.reset(WebKit::webKitClient()->createURLLoader());
|
| +
|
| + // Start the resource loading.
|
| + url_loader_->loadAsynchronously(request, this);
|
| }
|
|
|
| void BufferedResourceLoader::Stop() {
|
| @@ -153,14 +174,15 @@ void BufferedResourceLoader::Stop() {
|
| // Destroy internal buffer.
|
| buffer_.reset();
|
|
|
| - if (bridge_.get()) {
|
| - // Cancel the request. This method call will cancel the request
|
| - // asynchronously. We may still get data or messages until we receive
|
| - // a response completed message.
|
| + if (url_loader_.get()) {
|
| if (deferred_)
|
| - bridge_->SetDefersLoading(false);
|
| + url_loader_->setDefersLoading(false);
|
| deferred_ = false;
|
| - bridge_->Cancel();
|
| +
|
| + if (!completed_) {
|
| + url_loader_->cancel();
|
| + completed_ = true;
|
| + }
|
| }
|
| }
|
|
|
| @@ -231,38 +253,47 @@ void BufferedResourceLoader::SetAllowDefer(bool is_allowed) {
|
| DisableDeferIfNeeded();
|
| }
|
|
|
| +void BufferedResourceLoader::SetURLLoaderForTest(WebURLLoader* mock_loader) {
|
| + url_loader_.reset(mock_loader);
|
| + keep_test_loader_ = true;
|
| +}
|
| +
|
| /////////////////////////////////////////////////////////////////////////////
|
| -// BufferedResourceLoader,
|
| -// webkit_glue::ResourceLoaderBridge::Peer implementations
|
| -bool BufferedResourceLoader::OnReceivedRedirect(
|
| - const GURL& new_url,
|
| - const webkit_glue::ResourceResponseInfo& info,
|
| - bool* has_new_first_party_for_cookies,
|
| - GURL* new_first_party_for_cookies) {
|
| - DCHECK(bridge_.get());
|
| -
|
| - // Save the new URL.
|
| - url_ = new_url;
|
| - // TODO(wtc): should we return a new first party for cookies URL?
|
| - *has_new_first_party_for_cookies = false;
|
| +// BufferedResourceLoader, WebKit::WebURLLoaderClient implementations.
|
| +void BufferedResourceLoader::willSendRequest(
|
| + WebURLLoader* loader,
|
| + WebURLRequest& newRequest,
|
| + const WebURLResponse& redirectResponse) {
|
|
|
| // The load may have been stopped and |start_callback| is destroyed.
|
| // In this case we shouldn't do anything.
|
| - if (!start_callback_.get())
|
| - return true;
|
| + if (!start_callback_.get()) {
|
| + // Set the url in the request to an invalid value (empty url).
|
| + newRequest.setURL(WebKit::WebURL());
|
| + return;
|
| + }
|
|
|
| - if (!IsProtocolSupportedForMedia(new_url)) {
|
| + if (!IsProtocolSupportedForMedia(newRequest.url())) {
|
| + // Set the url in the request to an invalid value (empty url).
|
| + newRequest.setURL(WebKit::WebURL());
|
| DoneStart(net::ERR_ADDRESS_INVALID);
|
| Stop();
|
| - return false;
|
| + return;
|
| }
|
| - return true;
|
| +
|
| + url_ = newRequest.url();
|
| }
|
|
|
| -void BufferedResourceLoader::OnReceivedResponse(
|
| - const webkit_glue::ResourceResponseInfo& info,
|
| - bool content_filtered) {
|
| - DCHECK(bridge_.get());
|
| +void BufferedResourceLoader::didSendData(
|
| + WebURLLoader* loader,
|
| + unsigned long long bytes_sent,
|
| + unsigned long long total_bytes_to_be_sent) {
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +void BufferedResourceLoader::didReceiveResponse(
|
| + WebURLLoader* loader,
|
| + const WebURLResponse& response) {
|
|
|
| // The loader may have been stopped and |start_callback| is destroyed.
|
| // In this case we shouldn't do anything.
|
| @@ -275,23 +306,18 @@ void BufferedResourceLoader::OnReceivedResponse(
|
| // response for HTTP and HTTPS protocol.
|
| if (IsHttpProtocol(url_)) {
|
| int error = net::OK;
|
| - if (!info.headers) {
|
| - // We expect to receive headers because this is a HTTP or HTTPS protocol,
|
| - // if not report failure.
|
| - error = net::ERR_INVALID_RESPONSE;
|
| - } else {
|
| - if (info.headers->response_code() == kHttpPartialContent)
|
| - partial_response_ = true;
|
| -
|
| - if (range_requested_ && partial_response_) {
|
| - // If we have verified the partial response and it is correct, we will
|
| - // return net::OK.
|
| - if (!VerifyPartialResponse(info))
|
| - error = net::ERR_INVALID_RESPONSE;
|
| - } else if (info.headers->response_code() != kHttpOK) {
|
| - // We didn't request a range but server didn't reply with "200 OK".
|
| - error = net::ERR_FAILED;
|
| - }
|
| +
|
| + if (response.httpStatusCode() == kHttpPartialContent)
|
| + partial_response_ = true;
|
| +
|
| + if (range_requested_ && partial_response_) {
|
| + // If we have verified the partial response and it is correct, we will
|
| + // return net::OK.
|
| + if (!VerifyPartialResponse(response))
|
| + error = net::ERR_INVALID_RESPONSE;
|
| + } else if (response.httpStatusCode() != kHttpOK) {
|
| + // We didn't request a range but server didn't reply with "200 OK".
|
| + error = net::ERR_FAILED;
|
| }
|
|
|
| if (error != net::OK) {
|
| @@ -305,9 +331,9 @@ void BufferedResourceLoader::OnReceivedResponse(
|
| partial_response_ = range_requested_;
|
| }
|
|
|
| - // |info.content_length| can be -1, in that case |content_length_| is
|
| + // Expected content length can be -1, in that case |content_length_| is
|
| // not specified and this is a streaming response.
|
| - content_length_ = info.content_length;
|
| + content_length_ = response.expectedContentLength();
|
|
|
| // If we have not requested a range, then the size of the instance is equal
|
| // to the content length.
|
| @@ -318,8 +344,12 @@ void BufferedResourceLoader::OnReceivedResponse(
|
| DoneStart(net::OK);
|
| }
|
|
|
| -void BufferedResourceLoader::OnReceivedData(const char* data, int len) {
|
| - DCHECK(bridge_.get());
|
| +void BufferedResourceLoader::didReceiveData(
|
| + WebURLLoader* loader,
|
| + const char* data,
|
| + int data_length) {
|
| + DCHECK(!completed_);
|
| + DCHECK_GT(data_length, 0);
|
|
|
| // If this loader has been stopped, |buffer_| would be destroyed.
|
| // In this case we shouldn't do anything.
|
| @@ -327,7 +357,7 @@ void BufferedResourceLoader::OnReceivedData(const char* data, int len) {
|
| return;
|
|
|
| // Writes more data to |buffer_|.
|
| - buffer_->Append(reinterpret_cast<const uint8*>(data), len);
|
| + buffer_->Append(reinterpret_cast<const uint8*>(data), data_length);
|
|
|
| // If there is an active read request, try to fulfill the request.
|
| if (HasPendingRead() && CanFulfillRead()) {
|
| @@ -350,18 +380,28 @@ void BufferedResourceLoader::OnReceivedData(const char* data, int len) {
|
| NotifyNetworkEvent();
|
| }
|
|
|
| -void BufferedResourceLoader::OnCompletedRequest(
|
| - const URLRequestStatus& status,
|
| - const std::string& security_info,
|
| - const base::Time& completion_time) {
|
| - DCHECK(bridge_.get());
|
| +void BufferedResourceLoader::didDownloadData(
|
| + WebKit::WebURLLoader* loader,
|
| + int dataLength) {
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +void BufferedResourceLoader::didReceiveCachedMetadata(
|
| + WebURLLoader* loader,
|
| + const char* data,
|
| + int data_length) {
|
| + NOTIMPLEMENTED();
|
| +}
|
|
|
| - // Saves the information that the request has completed.
|
| +void BufferedResourceLoader::didFinishLoading(
|
| + WebURLLoader* loader,
|
| + double finishTime) {
|
| + DCHECK(!completed_);
|
| completed_ = true;
|
|
|
| // If there is a start callback, calls it.
|
| if (start_callback_.get()) {
|
| - DoneStart(status.os_error());
|
| + DoneStart(net::OK);
|
| }
|
|
|
| // If there is a pending read but the request has ended, returns with what
|
| @@ -370,16 +410,11 @@ void BufferedResourceLoader::OnCompletedRequest(
|
| // Make sure we have a valid buffer before we satisfy a read request.
|
| DCHECK(buffer_.get());
|
|
|
| - if (status.is_success()) {
|
| - // Try to fulfill with what is in the buffer.
|
| - if (CanFulfillRead())
|
| - ReadInternal();
|
| - else
|
| - DoneRead(net::ERR_CACHE_MISS);
|
| - } else {
|
| - // If the request has failed, then fail the read.
|
| - DoneRead(net::ERR_FAILED);
|
| - }
|
| + // Try to fulfill with what is in the buffer.
|
| + if (CanFulfillRead())
|
| + ReadInternal();
|
| + else
|
| + DoneRead(net::ERR_CACHE_MISS);
|
| }
|
|
|
| // There must not be any outstanding read request.
|
| @@ -388,10 +423,31 @@ void BufferedResourceLoader::OnCompletedRequest(
|
| // Notify that network response is completed.
|
| NotifyNetworkEvent();
|
|
|
| - // We incremented the reference count when the loader was started. We balance
|
| - // that reference here so that we get destroyed. This is also the only safe
|
| - // place to destroy the ResourceLoaderBridge.
|
| - bridge_.reset();
|
| + url_loader_.reset();
|
| + Release();
|
| +}
|
| +
|
| +void BufferedResourceLoader::didFail(
|
| + WebURLLoader* loader,
|
| + const WebURLError& error) {
|
| + DCHECK(!completed_);
|
| + completed_ = true;
|
| +
|
| + // If there is a start callback, calls it.
|
| + if (start_callback_.get()) {
|
| + DoneStart(error.reason);
|
| + }
|
| +
|
| + // If there is a pending read but the request failed, return with the
|
| + // reason for the error.
|
| + if (HasPendingRead()) {
|
| + DoneRead(error.reason);
|
| + }
|
| +
|
| + // Notify that network response is completed.
|
| + NotifyNetworkEvent();
|
| +
|
| + url_loader_.reset();
|
| Release();
|
| }
|
|
|
| @@ -405,8 +461,8 @@ void BufferedResourceLoader::EnableDeferIfNeeded() {
|
| buffer_->forward_bytes() >= buffer_->forward_capacity()) {
|
| deferred_ = true;
|
|
|
| - if (bridge_.get())
|
| - bridge_->SetDefersLoading(true);
|
| + if (url_loader_.get())
|
| + url_loader_->setDefersLoading(true);
|
|
|
| NotifyNetworkEvent();
|
| }
|
| @@ -418,8 +474,8 @@ void BufferedResourceLoader::DisableDeferIfNeeded() {
|
| buffer_->forward_bytes() < buffer_->forward_capacity() / 2)) {
|
| deferred_ = false;
|
|
|
| - if (bridge_.get())
|
| - bridge_->SetDefersLoading(false);
|
| + if (url_loader_.get())
|
| + url_loader_->setDefersLoading(false);
|
|
|
| NotifyNetworkEvent();
|
| }
|
| @@ -480,18 +536,21 @@ void BufferedResourceLoader::ReadInternal() {
|
| }
|
|
|
| bool BufferedResourceLoader::VerifyPartialResponse(
|
| - const ResourceResponseInfo& info) {
|
| - int64 first_byte_position, last_byte_position, instance_size;
|
| - if (!info.headers->GetContentRange(&first_byte_position,
|
| - &last_byte_position,
|
| - &instance_size)) {
|
| + const WebURLResponse& response) {
|
| + int first_byte_position, last_byte_position, instance_size;
|
| +
|
| + if (!MultipartResponseDelegate::ReadContentRanges(response,
|
| + &first_byte_position,
|
| + &last_byte_position,
|
| + &instance_size)) {
|
| return false;
|
| }
|
|
|
| - if (instance_size != kPositionNotSpecified)
|
| + if (instance_size != kPositionNotSpecified) {
|
| instance_size_ = instance_size;
|
| + }
|
|
|
| - if (first_byte_position_ != -1 &&
|
| + if (first_byte_position_ != kPositionNotSpecified &&
|
| first_byte_position_ != first_byte_position) {
|
| return false;
|
| }
|
| @@ -501,6 +560,27 @@ bool BufferedResourceLoader::VerifyPartialResponse(
|
| return true;
|
| }
|
|
|
| +std::string BufferedResourceLoader::GenerateHeaders(
|
| + int64 first_byte_position,
|
| + int64 last_byte_position) {
|
| + // Construct the value for the range header.
|
| + std::string header;
|
| + if (first_byte_position > kPositionNotSpecified &&
|
| + last_byte_position > kPositionNotSpecified) {
|
| + if (first_byte_position <= last_byte_position) {
|
| + header = base::StringPrintf("bytes=%" PRId64 "-%" PRId64,
|
| + first_byte_position,
|
| + last_byte_position);
|
| + }
|
| + } else if (first_byte_position > kPositionNotSpecified) {
|
| + header = base::StringPrintf("bytes=%" PRId64 "-",
|
| + first_byte_position);
|
| + } else if (last_byte_position > kPositionNotSpecified) {
|
| + NOTIMPLEMENTED() << "Suffix range not implemented";
|
| + }
|
| + return header;
|
| +}
|
| +
|
| void BufferedResourceLoader::DoneRead(int error) {
|
| read_callback_->RunWithParams(Tuple1<int>(error));
|
| read_callback_.reset();
|
| @@ -525,12 +605,12 @@ void BufferedResourceLoader::NotifyNetworkEvent() {
|
| // BufferedDataSource
|
| BufferedDataSource::BufferedDataSource(
|
| MessageLoop* render_loop,
|
| - webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory)
|
| + WebFrame* frame)
|
| : total_bytes_(kPositionNotSpecified),
|
| loaded_(false),
|
| streaming_(false),
|
| + frame_(frame),
|
| single_origin_(true),
|
| - bridge_factory_(bridge_factory),
|
| loader_(NULL),
|
| network_activity_(false),
|
| initialize_callback_(NULL),
|
| @@ -558,7 +638,7 @@ BufferedResourceLoader* BufferedDataSource::CreateResourceLoader(
|
| int64 first_byte_position, int64 last_byte_position) {
|
| DCHECK(MessageLoop::current() == render_loop_);
|
|
|
| - return new BufferedResourceLoader(bridge_factory_.get(), url_,
|
| + return new BufferedResourceLoader(url_,
|
| first_byte_position,
|
| last_byte_position);
|
| }
|
| @@ -658,12 +738,12 @@ void BufferedDataSource::Abort() {
|
| // If we are told to abort, immediately return from any pending read
|
| // with an error.
|
| if (read_callback_.get()) {
|
| - {
|
| AutoLock auto_lock(lock_);
|
| DoneRead_Locked(net::ERR_FAILED);
|
| - }
|
| - CleanupTask();
|
| }
|
| +
|
| + CleanupTask();
|
| + frame_ = NULL;
|
| }
|
|
|
| /////////////////////////////////////////////////////////////////////////////
|
| @@ -690,7 +770,8 @@ void BufferedDataSource::InitializeTask() {
|
| loader_ = CreateResourceLoader(0, 1024);
|
| loader_->Start(
|
| NewCallback(this, &BufferedDataSource::HttpInitialStartCallback),
|
| - NewCallback(this, &BufferedDataSource::NetworkEventCallback));
|
| + NewCallback(this, &BufferedDataSource::NetworkEventCallback),
|
| + frame_);
|
| } else {
|
| // For all other protocols, assume they support range request. We fetch
|
| // the full range of the resource to obtain the instance size because
|
| @@ -698,7 +779,8 @@ void BufferedDataSource::InitializeTask() {
|
| loader_ = CreateResourceLoader(-1, -1);
|
| loader_->Start(
|
| NewCallback(this, &BufferedDataSource::NonHttpInitialStartCallback),
|
| - NewCallback(this, &BufferedDataSource::NetworkEventCallback));
|
| + NewCallback(this, &BufferedDataSource::NetworkEventCallback),
|
| + frame_);
|
| }
|
| }
|
|
|
| @@ -775,7 +857,8 @@ void BufferedDataSource::RestartLoadingTask() {
|
| loader_->SetAllowDefer(!media_is_paused_);
|
| loader_->Start(
|
| NewCallback(this, &BufferedDataSource::PartialReadStartCallback),
|
| - NewCallback(this, &BufferedDataSource::NetworkEventCallback));
|
| + NewCallback(this, &BufferedDataSource::NetworkEventCallback),
|
| + frame_);
|
| }
|
|
|
| void BufferedDataSource::WatchDogTask() {
|
| @@ -806,7 +889,8 @@ void BufferedDataSource::WatchDogTask() {
|
| loader_->SetAllowDefer(!media_is_paused_);
|
| loader_->Start(
|
| NewCallback(this, &BufferedDataSource::PartialReadStartCallback),
|
| - NewCallback(this, &BufferedDataSource::NetworkEventCallback));
|
| + NewCallback(this, &BufferedDataSource::NetworkEventCallback),
|
| + frame_);
|
| }
|
|
|
| void BufferedDataSource::SetPlaybackRateTask(float playback_rate) {
|
| @@ -829,7 +913,7 @@ void BufferedDataSource::SetPlaybackRateTask(float playback_rate) {
|
| // prior to make this method call.
|
| void BufferedDataSource::ReadInternal() {
|
| DCHECK(MessageLoop::current() == render_loop_);
|
| - DCHECK(loader_.get());
|
| + DCHECK(loader_);
|
|
|
| // First we prepare the intermediate read buffer for BufferedResourceLoader
|
| // to write to.
|
| @@ -904,7 +988,8 @@ void BufferedDataSource::HttpInitialStartCallback(int error) {
|
| loader_ = CreateResourceLoader(-1, -1);
|
| loader_->Start(
|
| NewCallback(this, &BufferedDataSource::HttpInitialStartCallback),
|
| - NewCallback(this, &BufferedDataSource::NetworkEventCallback));
|
| + NewCallback(this, &BufferedDataSource::NetworkEventCallback),
|
| + frame_);
|
| return;
|
| }
|
|
|
|
|