diff options
39 files changed, 1315 insertions, 698 deletions
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc index 88f5c75..867743c 100644 --- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc @@ -42,10 +42,10 @@ #include "extensions/common/features/feature.h" #include "net/base/auth.h" #include "net/base/capturing_net_log.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/net_util.h" #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" #include "net/dns/mock_host_resolver.h" #include "net/url_request/url_request_job_factory_impl.h" @@ -520,7 +520,7 @@ void ExtensionWebRequestTest::FireURLRequestWithData( element_readers.push_back( new net::UploadBytesElementReader(&(bytes_2[0]), bytes_2.size())); request->set_upload(make_scoped_ptr( - new net::UploadDataStream(element_readers.Pass(), 0))); + new net::ElementsUploadDataStream(element_readers.Pass(), 0))); ipc_sender_.PushTask(base::Bind(&base::DoNothing)); request->Start(); } diff --git a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc index 5aef283..b95d0fc 100644 --- a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc +++ b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc @@ -11,10 +11,10 @@ #include "base/stl_util.h" #include "base/time/time.h" #include "chrome/browser/net/cert_logger.pb.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/load_flags.h" #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/cert/x509_certificate.h" #include "net/ssl/ssl_info.h" #include "net/url_request/url_request_context.h" @@ -84,8 +84,8 @@ void ChromeFraudulentCertificateReporter::SendReport( scoped_ptr<net::UploadElementReader> reader( net::UploadOwnedBytesElementReader::CreateWithString(report)); - url_request->set_upload(make_scoped_ptr( - net::UploadDataStream::CreateWithReader(reader.Pass(), 0))); + url_request->set_upload( + net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0)); net::HttpRequestHeaders headers; headers.SetHeader(net::HttpRequestHeaders::kContentType, diff --git a/chrome/browser/policy/cloud/device_management_service_browsertest.cc b/chrome/browser/policy/cloud/device_management_service_browsertest.cc index c757045..034aacb 100644 --- a/chrome/browser/policy/cloud/device_management_service_browsertest.cc +++ b/chrome/browser/policy/cloud/device_management_service_browsertest.cc @@ -68,11 +68,12 @@ net::URLRequestJob* ResponseJob( net::NetworkDelegate* network_delegate) { const net::UploadDataStream* upload = request->get_upload(); if (upload != NULL && - upload->element_readers().size() == 1 && - upload->element_readers()[0]->AsBytesReader()) { + upload->GetElementReaders() && + upload->GetElementReaders()->size() == 1 && + (*upload->GetElementReaders())[0]->AsBytesReader()) { std::string response_data; const net::UploadBytesElementReader* bytes_reader = - upload->element_readers()[0]->AsBytesReader(); + (*upload->GetElementReaders())[0]->AsBytesReader(); ConstructResponse(bytes_reader->bytes(), bytes_reader->length(), &response_data); diff --git a/chrome/browser/policy/cloud/test_request_interceptor.cc b/chrome/browser/policy/cloud/test_request_interceptor.cc index 967e470..5069ca8 100644 --- a/chrome/browser/policy/cloud/test_request_interceptor.cc +++ b/chrome/browser/policy/cloud/test_request_interceptor.cc @@ -81,11 +81,11 @@ bool ValidRequest(net::URLRequest* request, const net::UploadDataStream* stream = request->get_upload(); if (!stream) return false; - const ScopedVector<net::UploadElementReader>& readers = - stream->element_readers(); - if (readers.size() != 1u) + const ScopedVector<net::UploadElementReader>* readers = + stream->GetElementReaders(); + if (!readers || readers->size() != 1u) return false; - const net::UploadBytesElementReader* reader = readers[0]->AsBytesReader(); + const net::UploadBytesElementReader* reader = (*readers)[0]->AsBytesReader(); if (!reader) return false; std::string data(reader->bytes(), reader->length()); diff --git a/chrome/browser/sessions/better_session_restore_browsertest.cc b/chrome/browser/sessions/better_session_restore_browsertest.cc index 29d270b..d50a258 100644 --- a/chrome/browser/sessions/better_session_restore_browsertest.cc +++ b/chrome/browser/sessions/better_session_restore_browsertest.cc @@ -80,14 +80,16 @@ net::URLRequestJob* URLRequestFakerForPostRequests( const net::UploadDataStream* upload_data = request->get_upload(); g_last_upload_bytes.Get().clear(); if (upload_data) { - const ScopedVector<net::UploadElementReader>& readers = - upload_data->element_readers(); - for (size_t i = 0; i < readers.size(); ++i) { - const net::UploadBytesElementReader* bytes_reader = - readers[i]->AsBytesReader(); - if (bytes_reader) { - g_last_upload_bytes.Get() += - std::string(bytes_reader->bytes(), bytes_reader->length()); + const ScopedVector<net::UploadElementReader>* readers = + upload_data->GetElementReaders(); + if (readers) { + for (size_t i = 0; i < readers->size(); ++i) { + const net::UploadBytesElementReader* bytes_reader = + (*readers)[i]->AsBytesReader(); + if (bytes_reader) { + g_last_upload_bytes.Get() += + std::string(bytes_reader->bytes(), bytes_reader->length()); + } } } } diff --git a/cloud_print/service/service_state.cc b/cloud_print/service/service_state.cc index 30e191b..59554bb 100644 --- a/cloud_print/service/service_state.cc +++ b/cloud_print/service/service_state.cc @@ -10,12 +10,12 @@ #include "base/message_loop/message_loop.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/escape.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_builder.h" @@ -184,8 +184,8 @@ std::string ServiceState::LoginToGoogle(const std::string& service, scoped_ptr<net::UploadElementReader> reader( net::UploadOwnedBytesElementReader::CreateWithString(post_body)); - request->set_upload(make_scoped_ptr( - net::UploadDataStream::CreateWithReader(reader.Pass(), 0))); + request->set_upload( + net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0)); request->SetExtraRequestHeaderByName( "Content-Type", "application/x-www-form-urlencoded", true); request->set_method("POST"); diff --git a/components/component_updater/test/url_request_post_interceptor.cc b/components/component_updater/test/url_request_post_interceptor.cc index 882db72..2dd474a 100644 --- a/components/component_updater/test/url_request_post_interceptor.cc +++ b/components/component_updater/test/url_request_post_interceptor.cc @@ -10,6 +10,7 @@ #include "base/strings/stringprintf.h" #include "components/component_updater/test/test_configurator.h" #include "net/base/upload_bytes_element_reader.h" +#include "net/base/upload_data_stream.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_filter.h" #include "net/url_request/url_request_interceptor.h" @@ -198,7 +199,7 @@ class URLRequestPostInterceptor::Delegate : public net::URLRequestInterceptor { const net::UploadDataStream* stream = request->get_upload(); const net::UploadBytesElementReader* reader = - stream->element_readers()[0]->AsBytesReader(); + (*stream->GetElementReaders())[0]->AsBytesReader(); const int size = reader->length(); scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size)); const std::string request_body(reader->bytes()); diff --git a/components/cronet/android/url_request_adapter.cc b/components/cronet/android/url_request_adapter.cc index 9d9e29b..8bba40d0 100644 --- a/components/cronet/android/url_request_adapter.cc +++ b/components/cronet/android/url_request_adapter.cc @@ -12,6 +12,7 @@ #include "base/strings/string_number_conversions.h" #include "components/cronet/android/url_request_context_adapter.h" #include "components/cronet/android/wrapped_channel_upload_element_reader.h" +#include "net/base/element_upload_data_stream.h" #include "net/base/load_flags.h" #include "net/base/upload_bytes_element_reader.h" #include "net/http/http_status_code.h" @@ -56,15 +57,15 @@ void URLRequestAdapter::SetUploadContent(const char* bytes, int bytes_len) { std::vector<char> data(bytes, bytes + bytes_len); scoped_ptr<net::UploadElementReader> reader( new net::UploadOwnedBytesElementReader(&data)); - upload_data_stream_.reset( - net::UploadDataStream::CreateWithReader(reader.Pass(), 0)); + upload_data_stream_ = + net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0); } void URLRequestAdapter::SetUploadChannel(JNIEnv* env, int64 content_length) { scoped_ptr<net::UploadElementReader> reader( new WrappedChannelElementReader(delegate_, content_length)); - upload_data_stream_.reset( - net::UploadDataStream::CreateWithReader(reader.Pass(), 0)); + upload_data_stream_ = + net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0); } void URLRequestAdapter::EnableChunkedUpload() { diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index e620f19..0ef4729 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc @@ -39,10 +39,10 @@ #include "content/public/browser/resource_context.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/common/referrer.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/load_flags.h" #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/url_request/url_request_context.h" namespace content { @@ -63,8 +63,8 @@ void BeginDownload(scoped_ptr<DownloadUrlParameters> params, const std::string& body = params->post_body(); scoped_ptr<net::UploadElementReader> reader( net::UploadOwnedBytesElementReader::CreateWithString(body)); - request->set_upload(make_scoped_ptr( - net::UploadDataStream::CreateWithReader(reader.Pass(), 0))); + request->set_upload( + net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0)); } if (params->post_id() >= 0) { // The POST in this case does not have an actual body, and only works @@ -75,7 +75,8 @@ void BeginDownload(scoped_ptr<DownloadUrlParameters> params, DCHECK_EQ("POST", params->method()); ScopedVector<net::UploadElementReader> element_readers; request->set_upload(make_scoped_ptr( - new net::UploadDataStream(element_readers.Pass(), params->post_id()))); + new net::ElementsUploadDataStream(element_readers.Pass(), + params->post_id()))); } // If we're not at the beginning of the file, retrieve only the remaining diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index a78acea..31ed3f1 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc @@ -37,10 +37,10 @@ #include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/test/test_content_browser_client.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/net_errors.h" #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/http/http_util.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" @@ -1779,8 +1779,8 @@ TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) { std::fill(upload_content.begin(), upload_content.end(), 'x'); scoped_ptr<net::UploadElementReader> reader(new net::UploadBytesElementReader( upload_content.data(), upload_content.size())); - req->set_upload(make_scoped_ptr( - net::UploadDataStream::CreateWithReader(reader.Pass(), 0))); + req->set_upload( + net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0)); // Since the upload throttling is disabled, this has no effect on the cost. EXPECT_EQ( diff --git a/content/browser/loader/upload_data_stream_builder.cc b/content/browser/loader/upload_data_stream_builder.cc index e68c193..45b22b6 100644 --- a/content/browser/loader/upload_data_stream_builder.cc +++ b/content/browser/loader/upload_data_stream_builder.cc @@ -7,8 +7,8 @@ #include "base/logging.h" #include "content/browser/fileapi/upload_file_system_file_element_reader.h" #include "content/common/resource_request_body.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" @@ -134,7 +134,8 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build( } return make_scoped_ptr( - new net::UploadDataStream(element_readers.Pass(), body->identifier())); + new net::ElementsUploadDataStream(element_readers.Pass(), + body->identifier())); } } // namespace content diff --git a/content/browser/loader/upload_data_stream_builder_unittest.cc b/content/browser/loader/upload_data_stream_builder_unittest.cc index 72e9ecb6..dfd22b2 100644 --- a/content/browser/loader/upload_data_stream_builder_unittest.cc +++ b/content/browser/loader/upload_data_stream_builder_unittest.cc @@ -76,15 +76,17 @@ TEST(UploadDataStreamBuilderTest, CreateUploadDataStreamWithoutBlob) { request_body.get(), NULL, NULL, base::MessageLoopProxy::current().get())); EXPECT_EQ(kIdentifier, upload->identifier()); - ASSERT_EQ(request_body->elements()->size(), upload->element_readers().size()); + ASSERT_TRUE(upload->GetElementReaders()); + ASSERT_EQ(request_body->elements()->size(), + upload->GetElementReaders()->size()); const net::UploadBytesElementReader* r1 = - upload->element_readers()[0]->AsBytesReader(); + (*upload->GetElementReaders())[0]->AsBytesReader(); ASSERT_TRUE(r1); EXPECT_EQ(kData, std::string(r1->bytes(), r1->length())); const net::UploadFileElementReader* r2 = - upload->element_readers()[1]->AsFileReader(); + (*upload->GetElementReaders())[1]->AsFileReader(); ASSERT_TRUE(r2); EXPECT_EQ(kFilePath, r2->path().value()); EXPECT_EQ(kFileOffset, r2->range_offset()); @@ -150,11 +152,12 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { NULL, base::MessageLoopProxy::current().get())); - ASSERT_EQ(2U, upload->element_readers().size()); + ASSERT_TRUE(upload->GetElementReaders()); + ASSERT_EQ(2U, upload->GetElementReaders()->size()); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[0], upload_element1)); + *(*upload->GetElementReaders())[0], upload_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[1], upload_element2)); + *(*upload->GetElementReaders())[1], upload_element2)); // Test having only one blob reference that refers to empty blob data. request_body = new ResourceRequestBody(); @@ -165,7 +168,8 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); - ASSERT_EQ(0U, upload->element_readers().size()); + ASSERT_TRUE(upload->GetElementReaders()); + ASSERT_EQ(0U, upload->GetElementReaders()->size()); // Test having only one blob reference. request_body = new ResourceRequestBody(); @@ -176,11 +180,12 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); - ASSERT_EQ(2U, upload->element_readers().size()); + ASSERT_TRUE(upload->GetElementReaders()); + ASSERT_EQ(2U, upload->GetElementReaders()->size()); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[0], blob_element1)); + *(*upload->GetElementReaders())[0], blob_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[1], blob_element2)); + *(*upload->GetElementReaders())[1], blob_element2)); // Test having one blob reference at the beginning. request_body = new ResourceRequestBody(); @@ -199,15 +204,16 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); - ASSERT_EQ(4U, upload->element_readers().size()); + ASSERT_TRUE(upload->GetElementReaders()); + ASSERT_EQ(4U, upload->GetElementReaders()->size()); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[0], blob_element1)); + *(*upload->GetElementReaders())[0], blob_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[1], blob_element2)); + *(*upload->GetElementReaders())[1], blob_element2)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[2], upload_element1)); + *(*upload->GetElementReaders())[2], upload_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[3], upload_element2)); + *(*upload->GetElementReaders())[3], upload_element2)); // Test having one blob reference at the end. request_body = new ResourceRequestBody(); @@ -226,15 +232,16 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); - ASSERT_EQ(4U, upload->element_readers().size()); + ASSERT_TRUE(upload->GetElementReaders()); + ASSERT_EQ(4U, upload->GetElementReaders()->size()); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[0], upload_element1)); + *(*upload->GetElementReaders())[0], upload_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[1], upload_element2)); + *(*upload->GetElementReaders())[1], upload_element2)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[2], blob_element1)); + *(*upload->GetElementReaders())[2], blob_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[3], blob_element2)); + *(*upload->GetElementReaders())[3], blob_element2)); // Test having one blob reference in the middle. request_body = new ResourceRequestBody(); @@ -253,15 +260,16 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); - ASSERT_EQ(4U, upload->element_readers().size()); + ASSERT_TRUE(upload->GetElementReaders()); + ASSERT_EQ(4U, upload->GetElementReaders()->size()); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[0], upload_element1)); + *(*upload->GetElementReaders())[0], upload_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[1], blob_element1)); + *(*upload->GetElementReaders())[1], blob_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[2], blob_element2)); + *(*upload->GetElementReaders())[2], blob_element2)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[3], upload_element2)); + *(*upload->GetElementReaders())[3], upload_element2)); // Test having multiple blob references. request_body = new ResourceRequestBody(); @@ -282,23 +290,24 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) { &blob_storage_context, NULL, base::MessageLoopProxy::current().get()); - ASSERT_EQ(8U, upload->element_readers().size()); + ASSERT_TRUE(upload->GetElementReaders()); + ASSERT_EQ(8U, upload->GetElementReaders()->size()); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[0], blob_element1)); + *(*upload->GetElementReaders())[0], blob_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[1], blob_element2)); + *(*upload->GetElementReaders())[1], blob_element2)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[2], upload_element1)); + *(*upload->GetElementReaders())[2], upload_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[3], blob_element1)); + *(*upload->GetElementReaders())[3], blob_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[4], blob_element2)); + *(*upload->GetElementReaders())[4], blob_element2)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[5], blob_element1)); + *(*upload->GetElementReaders())[5], blob_element1)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[6], blob_element2)); + *(*upload->GetElementReaders())[6], blob_element2)); EXPECT_TRUE(AreElementsEqual( - *upload->element_readers()[7], upload_element2)); + *(*upload->GetElementReaders())[7], upload_element2)); } // Clean up for ASAN. base::RunLoop().RunUntilIdle(); diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index afef67e..0157970 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc @@ -223,8 +223,8 @@ void ExtractRequestInfoBody(const net::URLRequest* request, (request->method() != "POST" && request->method() != "PUT")) return; // Need to exit without "out->Set(keys::kRequestBodyKey, ...);" . - base::DictionaryValue* requestBody = new base::DictionaryValue(); - out->Set(keys::kRequestBodyKey, requestBody); + base::DictionaryValue* request_body = new base::DictionaryValue(); + out->Set(keys::kRequestBodyKey, request_body); // Get the data presenters, ordered by how specific they are. extensions::ParsedDataPresenter parsed_data_presenter(*request); @@ -239,20 +239,22 @@ void ExtractRequestInfoBody(const net::URLRequest* request, keys::kRequestBodyRawKey }; - const ScopedVector<net::UploadElementReader>& readers = - upload_data->element_readers(); + const ScopedVector<net::UploadElementReader>* readers = + upload_data->GetElementReaders(); bool some_succeeded = false; - for (size_t i = 0; !some_succeeded && i < arraysize(presenters); ++i) { - ScopedVector<net::UploadElementReader>::const_iterator reader; - for (reader = readers.begin(); reader != readers.end(); ++reader) - presenters[i]->FeedNext(**reader); - if (presenters[i]->Succeeded()) { - requestBody->Set(kKeys[i], presenters[i]->Result().release()); - some_succeeded = true; + if (readers) { + for (size_t i = 0; !some_succeeded && i < arraysize(presenters); ++i) { + ScopedVector<net::UploadElementReader>::const_iterator reader; + for (reader = readers->begin(); reader != readers->end(); ++reader) + presenters[i]->FeedNext(**reader); + if (presenters[i]->Succeeded()) { + request_body->Set(kKeys[i], presenters[i]->Result().release()); + some_succeeded = true; + } } } if (!some_succeeded) - requestBody->SetString(keys::kRequestBodyErrorKey, "Unknown error."); + request_body->SetString(keys::kRequestBodyErrorKey, "Unknown error."); } // Converts a HttpHeaders dictionary to a |name|, |value| pair. Returns diff --git a/mojo/services/network/url_loader_impl.cc b/mojo/services/network/url_loader_impl.cc index 1be5ee2..a8c6030 100644 --- a/mojo/services/network/url_loader_impl.cc +++ b/mojo/services/network/url_loader_impl.cc @@ -9,10 +9,10 @@ #include "mojo/common/common_type_converters.h" #include "mojo/services/network/net_adapters.h" #include "mojo/services/network/network_context.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/http/http_response_headers.h" #include "net/url_request/redirect_info.h" #include "net/url_request/url_request_context.h" @@ -192,8 +192,8 @@ void URLLoaderImpl::Start(URLRequestPtr request, element_readers.push_back( new UploadDataPipeElementReader(request->body[i].Pass())); } - url_request_->set_upload(make_scoped_ptr( - new net::UploadDataStream(element_readers.Pass(), 0))); + url_request_->set_upload(make_scoped_ptr<net::UploadDataStream>( + new net::ElementsUploadDataStream(element_readers.Pass(), 0))); } if (request->bypass_cache) url_request_->SetLoadFlags(net::LOAD_BYPASS_CACHE); diff --git a/net/base/chunked_upload_data_stream.cc b/net/base/chunked_upload_data_stream.cc new file mode 100644 index 0000000..f1fbf08 --- /dev/null +++ b/net/base/chunked_upload_data_stream.cc @@ -0,0 +1,103 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/chunked_upload_data_stream.h" + +#include "base/logging.h" +#include "base/stl_util.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" + +namespace net { + +ChunkedUploadDataStream::ChunkedUploadDataStream(int64 identifier) + : UploadDataStream(true, identifier), + read_index_(0), + read_offset_(0), + all_data_appended_(false), + read_buffer_len_(0) { +} + +ChunkedUploadDataStream::~ChunkedUploadDataStream() { +} + +void ChunkedUploadDataStream::AppendData( + const char* data, int data_len, bool is_done) { + DCHECK(!all_data_appended_); + DCHECK(data_len > 0 || is_done); + if (data_len > 0) { + DCHECK(data); + upload_data_.push_back(new std::vector<char>(data, data + data_len)); + } + all_data_appended_ = is_done; + + if (!read_buffer_.get()) + return; + + int result = ReadChunk(read_buffer_.get(), read_buffer_len_); + // Shouldn't get an error or ERR_IO_PENDING. + DCHECK_GE(result, 0); + read_buffer_ = NULL; + read_buffer_len_ = 0; + OnReadCompleted(result); +} + +int ChunkedUploadDataStream::InitInternal() { + // ResetInternal should already have been called. + DCHECK(!read_buffer_.get()); + DCHECK_EQ(0u, read_index_); + DCHECK_EQ(0u, read_offset_); + return OK; +} + +int ChunkedUploadDataStream::ReadInternal(IOBuffer* buf, int buf_len) { + DCHECK_LT(0, buf_len); + DCHECK(!read_buffer_.get()); + + int result = ReadChunk(buf, buf_len); + if (result == ERR_IO_PENDING) { + read_buffer_ = buf; + read_buffer_len_ = buf_len; + } + return result; +} + +void ChunkedUploadDataStream::ResetInternal() { + read_buffer_ = NULL; + read_buffer_len_ = 0; + read_index_ = 0; + read_offset_ = 0; +} + +int ChunkedUploadDataStream::ReadChunk(IOBuffer* buf, int buf_len) { + // Copy as much data as possible from |upload_data_| to |buf|. + int bytes_read = 0; + while (read_index_ < upload_data_.size() && bytes_read < buf_len) { + std::vector<char>* data = upload_data_[read_index_]; + size_t bytes_to_read = + std::min(static_cast<size_t>(buf_len - bytes_read), + data->size() - read_offset_); + memcpy(buf->data() + bytes_read, + vector_as_array(data) + read_offset_, + bytes_to_read); + bytes_read += bytes_to_read; + read_offset_ += bytes_to_read; + if (read_offset_ == data->size()) { + read_index_++; + read_offset_ = 0; + } + } + DCHECK_LE(bytes_read, buf_len); + + // If no data was written, and not all data has been appended, return + // ERR_IO_PENDING. The read will be completed in the next call to AppendData. + if (bytes_read == 0 && !all_data_appended_) + return ERR_IO_PENDING; + + if (read_index_ == upload_data_.size() && all_data_appended_) + SetIsFinalChunk(); + return bytes_read; +} + +} // namespace net diff --git a/net/base/chunked_upload_data_stream.h b/net/base/chunked_upload_data_stream.h new file mode 100644 index 0000000..3ea1b78 --- /dev/null +++ b/net/base/chunked_upload_data_stream.h @@ -0,0 +1,63 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_CHUNKED_UPLOAD_DATA_STREAM_H_ +#define NET_BASE_CHUNKED_UPLOAD_DATA_STREAM_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_vector.h" +#include "net/base/completion_callback.h" +#include "net/base/net_export.h" +#include "net/base/upload_data_stream.h" + +namespace net { + +class IOBuffer; + +// Class with a push-based interface for uploading data. Buffers all data until +// the request is completed. Not recommended for uploading large amounts of +// seekable data, due to this buffering behavior. +class NET_EXPORT ChunkedUploadDataStream : public UploadDataStream { + public: + ChunkedUploadDataStream(int64 identifier); + + virtual ~ChunkedUploadDataStream(); + + // Adds data to the stream. |is_done| should be true if this is the last + // data to be appended. |data_len| must not be 0 unless |is_done| is true. + // Once called with |is_done| being true, must never be called again. + // TODO(mmenke): Consider using IOBuffers instead, to reduce data copies. + void AppendData(const char* data, int data_len, bool is_done); + + private: + // UploadDataStream implementation. + virtual int InitInternal() OVERRIDE; + virtual int ReadInternal(IOBuffer* buf, int buf_len) OVERRIDE; + virtual void ResetInternal() OVERRIDE; + + int ReadChunk(IOBuffer* buf, int buf_len); + + // Index and offset of next element of |upload_data_| to be read. + size_t read_index_; + size_t read_offset_; + + // True once all data has been appended to the stream. + bool all_data_appended_; + + ScopedVector<std::vector<char>> upload_data_; + + // Buffer to write the next read's data to. Only set when a call to + // ReadInternal reads no data. + scoped_refptr<IOBuffer> read_buffer_; + int read_buffer_len_; + + DISALLOW_COPY_AND_ASSIGN(ChunkedUploadDataStream); +}; + +} // namespace net + +#endif // NET_BASE_CHUNKED_UPLOAD_DATA_STREAM_H_ diff --git a/net/base/chunked_upload_data_stream_unittest.cc b/net/base/chunked_upload_data_stream_unittest.cc new file mode 100644 index 0000000..334e9a3 --- /dev/null +++ b/net/base/chunked_upload_data_stream_unittest.cc @@ -0,0 +1,308 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/chunked_upload_data_stream.h" + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "net/base/upload_data_stream.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +const char kTestData[] = "0123456789"; +const size_t kTestDataSize = arraysize(kTestData) - 1; +const size_t kTestBufferSize = 1 << 14; // 16KB. + +} // namespace + +// Reads data once from the upload data stream, and returns the data as string. +// Expects the read to succeed synchronously. +std::string ReadSync(UploadDataStream* stream, int buffer_size) { + scoped_refptr<IOBuffer> buf = new IOBuffer(buffer_size); + int result = stream->Read(buf.get(), + buffer_size, + TestCompletionCallback().callback()); + EXPECT_GE(result, 0); + return std::string(buf->data(), result); +} + +// Check the case data is added after the first read attempt. +TEST(ChunkedUploadDataStreamTest, AppendOnce) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + TestCompletionCallback callback; + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + int result = stream.Read(buf.get(), kTestBufferSize, callback.callback()); + ASSERT_EQ(ERR_IO_PENDING, result); + + stream.AppendData(kTestData, kTestDataSize, true); + int read = callback.WaitForResult(); + ASSERT_GE(read, 0); + EXPECT_EQ(kTestData, std::string(buf->data(), read)); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(kTestDataSize, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, AppendOnceBeforeRead) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + stream.AppendData(kTestData, kTestDataSize, true); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(kTestDataSize, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, AppendOnceBeforeInit) { + ChunkedUploadDataStream stream(0); + + stream.AppendData(kTestData, kTestDataSize, true); + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(kTestDataSize, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, MultipleAppends) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + TestCompletionCallback callback; + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + for (size_t i = 0; i < kTestDataSize; ++i) { + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(i, stream.position()); + ASSERT_FALSE(stream.IsEOF()); + int bytes_read = stream.Read(buf.get(), + kTestBufferSize, + callback.callback()); + ASSERT_EQ(ERR_IO_PENDING, bytes_read); + stream.AppendData(&kTestData[i], 1, i == kTestDataSize - 1); + ASSERT_EQ(1, callback.WaitForResult()); + EXPECT_EQ(kTestData[i], buf->data()[0]); + } + + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, MultipleAppendsBetweenReads) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + for (size_t i = 0; i < kTestDataSize; ++i) { + EXPECT_EQ(i, stream.position()); + ASSERT_FALSE(stream.IsEOF()); + stream.AppendData(&kTestData[i], 1, i == kTestDataSize - 1); + int bytes_read = stream.Read(buf.get(), + kTestBufferSize, + TestCompletionCallback().callback()); + ASSERT_EQ(1, bytes_read); + EXPECT_EQ(kTestData[i], buf->data()[0]); + } + + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); +} + +// Checks that multiple reads can be merged. +TEST(ChunkedUploadDataStreamTest, MultipleAppendsBeforeInit) { + ChunkedUploadDataStream stream(0); + stream.AppendData(kTestData, 1, false); + stream.AppendData(kTestData + 1, 1, false); + stream.AppendData(kTestData + 2, kTestDataSize - 2, true); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, MultipleReads) { + // Use a read size different from the write size to test bounds checking. + const size_t kReadSize = kTestDataSize + 3; + + ChunkedUploadDataStream stream(0); + stream.AppendData(kTestData, kTestDataSize, false); + stream.AppendData(kTestData, kTestDataSize, false); + stream.AppendData(kTestData, kTestDataSize, false); + stream.AppendData(kTestData, kTestDataSize, true); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kReadSize); + EXPECT_EQ("0123456789012", data); + EXPECT_EQ(kReadSize, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + data = ReadSync(&stream, kReadSize); + EXPECT_EQ("3456789012345", data); + EXPECT_EQ(2 * kReadSize, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + data = ReadSync(&stream, kReadSize); + EXPECT_EQ("6789012345678", data); + EXPECT_EQ(3 * kReadSize, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + data = ReadSync(&stream, kReadSize); + EXPECT_EQ("9", data); + EXPECT_EQ(4 * kTestDataSize, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, EmptyUpload) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + TestCompletionCallback callback; + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + int result = stream.Read(buf.get(), kTestBufferSize, callback.callback()); + ASSERT_EQ(ERR_IO_PENDING, result); + + stream.AppendData(NULL, 0, true); + int read = callback.WaitForResult(); + EXPECT_EQ(0, read); + EXPECT_EQ(0u, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, EmptyUploadEndedBeforeInit) { + ChunkedUploadDataStream stream(0); + stream.AppendData(NULL, 0, true); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + ASSERT_EQ("", data); + EXPECT_EQ(0u, stream.position()); + EXPECT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, RewindAfterComplete) { + ChunkedUploadDataStream stream(0); + stream.AppendData(kTestData, 1, false); + stream.AppendData(kTestData + 1, kTestDataSize - 1, true); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); + + // Rewind stream and repeat. + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); +} + +TEST(ChunkedUploadDataStreamTest, RewindWhileReading) { + ChunkedUploadDataStream stream(0); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + TestCompletionCallback callback; + scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); + int result = stream.Read(buf.get(), kTestBufferSize, callback.callback()); + ASSERT_EQ(ERR_IO_PENDING, result); + + ASSERT_EQ(OK, stream.Init(TestCompletionCallback().callback())); + EXPECT_FALSE(stream.IsInMemory()); + EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. + EXPECT_EQ(0u, stream.position()); + EXPECT_FALSE(stream.IsEOF()); + + // Adding data now should not result in calling the original read callback, + // since the stream was re-initialized for reuse, which cancels all pending + // reads. + stream.AppendData(kTestData, kTestDataSize, true); + EXPECT_FALSE(callback.have_result()); + + std::string data = ReadSync(&stream, kTestBufferSize); + EXPECT_EQ(kTestData, data); + EXPECT_EQ(kTestDataSize, stream.position()); + ASSERT_TRUE(stream.IsEOF()); + EXPECT_FALSE(callback.have_result()); +} + +} // namespace net diff --git a/net/base/elements_upload_data_stream.cc b/net/base/elements_upload_data_stream.cc new file mode 100644 index 0000000..86ea28c --- /dev/null +++ b/net/base/elements_upload_data_stream.cc @@ -0,0 +1,166 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/elements_upload_data_stream.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "net/base/completion_callback.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/base/upload_bytes_element_reader.h" +#include "net/base/upload_element_reader.h" + +namespace net { + +ElementsUploadDataStream::ElementsUploadDataStream( + ScopedVector<UploadElementReader> element_readers, + int64 identifier) + : UploadDataStream(false, identifier), + element_readers_(element_readers.Pass()), + element_index_(0), + read_failed_(false), + weak_ptr_factory_(this) { +} + +ElementsUploadDataStream::~ElementsUploadDataStream() { +} + +scoped_ptr<UploadDataStream> ElementsUploadDataStream::CreateWithReader( + scoped_ptr<UploadElementReader> reader, + int64 identifier) { + ScopedVector<UploadElementReader> readers; + readers.push_back(reader.release()); + return scoped_ptr<UploadDataStream>( + new ElementsUploadDataStream(readers.Pass(), identifier)); +} + +int ElementsUploadDataStream::InitInternal() { + return InitElements(0); +} + +int ElementsUploadDataStream::ReadInternal( + IOBuffer* buf, + int buf_len) { + DCHECK_GT(buf_len, 0); + return ReadElements(new DrainableIOBuffer(buf, buf_len)); +} + +bool ElementsUploadDataStream::IsInMemory() const { + for (size_t i = 0; i < element_readers_.size(); ++i) { + if (!element_readers_[i]->IsInMemory()) + return false; + } + return true; +} + +const ScopedVector<UploadElementReader>* +ElementsUploadDataStream::GetElementReaders() const { + return &element_readers_; +} + +void ElementsUploadDataStream::ResetInternal() { + weak_ptr_factory_.InvalidateWeakPtrs(); + read_failed_ = false; + element_index_ = 0; +} + +int ElementsUploadDataStream::InitElements(size_t start_index) { + // Call Init() for all elements. + for (size_t i = start_index; i < element_readers_.size(); ++i) { + UploadElementReader* reader = element_readers_[i]; + // When new_result is ERR_IO_PENDING, InitInternal() will be called + // with start_index == i + 1 when reader->Init() finishes. + int result = reader->Init( + base::Bind(&ElementsUploadDataStream::OnInitElementCompleted, + weak_ptr_factory_.GetWeakPtr(), + i)); + DCHECK(result != ERR_IO_PENDING || !reader->IsInMemory()); + DCHECK_LE(result, OK); + if (result != OK) + return result; + } + + uint64 total_size = 0; + for (size_t i = 0; i < element_readers_.size(); ++i) { + total_size += element_readers_[i]->GetContentLength(); + } + SetSize(total_size); + return OK; +} + +void ElementsUploadDataStream::OnInitElementCompleted(size_t index, + int result) { + DCHECK_NE(ERR_IO_PENDING, result); + + // Check the last result. + if (result == OK) + result = InitElements(index + 1); + + if (result != ERR_IO_PENDING) + OnInitCompleted(result); +} + +int ElementsUploadDataStream::ReadElements( + const scoped_refptr<DrainableIOBuffer>& buf) { + while (!read_failed_ && element_index_ < element_readers_.size()) { + UploadElementReader* reader = element_readers_[element_index_]; + + if (reader->BytesRemaining() == 0) { + ++element_index_; + continue; + } + + if (buf->BytesRemaining() == 0) + break; + + int result = reader->Read( + buf.get(), + buf->BytesRemaining(), + base::Bind(&ElementsUploadDataStream::OnReadElementCompleted, + weak_ptr_factory_.GetWeakPtr(), + buf)); + if (result == ERR_IO_PENDING) + return ERR_IO_PENDING; + ProcessReadResult(buf, result); + } + + if (read_failed_) { + // If an error occured during read operation, then pad with zero. + // Otherwise the server will hang waiting for the rest of the data. + int num_bytes_to_fill = std::min( + static_cast<uint64>(buf->BytesRemaining()), + size() - position() - buf->BytesConsumed()); + DCHECK_LE(0, num_bytes_to_fill); + memset(buf->data(), 0, num_bytes_to_fill); + buf->DidConsume(num_bytes_to_fill); + } + + return buf->BytesConsumed(); +} + +void ElementsUploadDataStream::OnReadElementCompleted( + const scoped_refptr<DrainableIOBuffer>& buf, + int result) { + ProcessReadResult(buf, result); + + result = ReadElements(buf); + if (result != ERR_IO_PENDING) + OnReadCompleted(result); +} + +void ElementsUploadDataStream::ProcessReadResult( + const scoped_refptr<DrainableIOBuffer>& buf, + int result) { + DCHECK_NE(ERR_IO_PENDING, result); + DCHECK(!read_failed_); + + if (result >= 0) { + buf->DidConsume(result); + } else { + read_failed_ = true; + } +} + +} // namespace net diff --git a/net/base/elements_upload_data_stream.h b/net/base/elements_upload_data_stream.h new file mode 100644 index 0000000..194deb3 --- /dev/null +++ b/net/base/elements_upload_data_stream.h @@ -0,0 +1,86 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_ELEMENTS_UPLOAD_DATA_STREAM_H_ +#define NET_BASE_ELEMENTS_UPLOAD_DATA_STREAM_H_ + +#include "base/basictypes.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" +#include "net/base/net_export.h" +#include "net/base/upload_data_stream.h" + +namespace net { + +class DrainableIOBuffer; +class IOBuffer; +class UploadElementReader; + +// A non-chunked UploadDataStream consisting of one or more UploadElements. +class NET_EXPORT ElementsUploadDataStream : public UploadDataStream { + public: + ElementsUploadDataStream(ScopedVector<UploadElementReader> element_readers, + int64 identifier); + + virtual ~ElementsUploadDataStream(); + + // Creates an ElementsUploadDataStream with a single reader. Returns a + // scoped_ptr<UploadDataStream> for ease of use. + static scoped_ptr<UploadDataStream> CreateWithReader( + scoped_ptr<UploadElementReader> reader, + int64 identifier); + + private: + // UploadDataStream implementation. + virtual bool IsInMemory() const OVERRIDE; + virtual const ScopedVector<UploadElementReader>* + GetElementReaders() const OVERRIDE; + virtual int InitInternal() OVERRIDE; + virtual int ReadInternal(IOBuffer* buf, int buf_len) OVERRIDE; + virtual void ResetInternal() OVERRIDE; + + // Runs Init() for all element readers. + // This method is used to implement InitInternal(). + int InitElements(size_t start_index); + + // Called when the |index| element finishes initialization. If it succeeded, + // continues with the |index + 1| element. Calls OnInitCompleted on error or + // when all elements have been initialized. + void OnInitElementCompleted(size_t index, int result); + + // Reads data from the element readers. + // This method is used to implement Read(). + int ReadElements(const scoped_refptr<DrainableIOBuffer>& buf); + + // Resumes pending read and calls OnReadCompleted with a result when + // necessary. + void OnReadElementCompleted(const scoped_refptr<DrainableIOBuffer>& buf, + int result); + + // Processes result of UploadElementReader::Read(). If |result| indicates + // success, updates |buf|'s offset. Otherwise, sets |read_failed_| to true. + void ProcessReadResult(const scoped_refptr<DrainableIOBuffer>& buf, + int result); + + ScopedVector<UploadElementReader> element_readers_; + + // Index of the current upload element (i.e. the element currently being + // read). The index is used as a cursor to iterate over elements in + // |upload_data_|. + size_t element_index_; + + // True if an error occcured during read operation. + bool read_failed_; + + base::WeakPtrFactory<ElementsUploadDataStream> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ElementsUploadDataStream); +}; + +} // namespace net + +#endif // NET_BASE_ELEMENTS_UPLOAD_DATA_STREAM_H_ diff --git a/net/base/upload_data_stream_unittest.cc b/net/base/elements_upload_data_stream_unittest.cc index 03c75d6..91c390c 100644 --- a/net/base/upload_data_stream_unittest.cc +++ b/net/base/elements_upload_data_stream_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/base/upload_data_stream.h" +#include "net/base/elements_upload_data_stream.h" #include <algorithm> #include <vector> @@ -20,6 +20,7 @@ #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/base/upload_bytes_element_reader.h" +#include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -122,13 +123,13 @@ class MockUploadElementReader : public UploadElementReader { } // namespace -class UploadDataStreamTest : public PlatformTest { +class ElementsUploadDataStreamTest : public PlatformTest { public: virtual void SetUp() { PlatformTest::SetUp(); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } - virtual ~UploadDataStreamTest() { + virtual ~ElementsUploadDataStreamTest() { element_readers_.clear(); base::RunLoop().RunUntilIdle(); } @@ -141,35 +142,37 @@ class UploadDataStreamTest : public PlatformTest { ScopedVector<UploadElementReader> element_readers_; }; -TEST_F(UploadDataStreamTest, EmptyUploadData) { - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_TRUE(stream.IsInMemory()); - EXPECT_EQ(0U, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_TRUE(stream.IsEOF()); +TEST_F(ElementsUploadDataStreamTest, EmptyUploadData) { + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(OK, stream->Init(CompletionCallback())); + EXPECT_TRUE(stream->IsInMemory()); + EXPECT_EQ(0U, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, ConsumeAllBytes) { +TEST_F(ElementsUploadDataStreamTest, ConsumeAllBytes) { element_readers_.push_back(new UploadBytesElementReader( kTestData, kTestDataSize)); - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_TRUE(stream.IsInMemory()); - EXPECT_EQ(kTestDataSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(OK, stream->Init(CompletionCallback())); + EXPECT_TRUE(stream->IsInMemory()); + EXPECT_EQ(kTestDataSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { + while (!stream->IsEOF()) { int bytes_read = - stream.Read(buf.get(), kTestBufferSize, CompletionCallback()); + stream->Read(buf.get(), kTestBufferSize, CompletionCallback()); ASSERT_LE(0, bytes_read); // Not an error. } - EXPECT_EQ(kTestDataSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize, stream->position()); + ASSERT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, File) { +TEST_F(ElementsUploadDataStreamTest, File) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -184,26 +187,27 @@ TEST_F(UploadDataStreamTest, File) { base::Time())); TestCompletionCallback init_callback; - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); ASSERT_EQ(OK, init_callback.WaitForResult()); - EXPECT_FALSE(stream.IsInMemory()); - EXPECT_EQ(kTestDataSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + EXPECT_FALSE(stream->IsInMemory()); + EXPECT_EQ(kTestDataSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { + while (!stream->IsEOF()) { TestCompletionCallback read_callback; ASSERT_EQ( ERR_IO_PENDING, - stream.Read(buf.get(), kTestBufferSize, read_callback.callback())); + stream->Read(buf.get(), kTestBufferSize, read_callback.callback())); ASSERT_LE(0, read_callback.WaitForResult()); // Not an error. } - EXPECT_EQ(kTestDataSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize, stream->position()); + ASSERT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, FileSmallerThanLength) { +TEST_F(ElementsUploadDataStreamTest, FileSmallerThanLength) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -222,32 +226,33 @@ TEST_F(UploadDataStreamTest, FileSmallerThanLength) { base::Time())); TestCompletionCallback init_callback; - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); ASSERT_EQ(OK, init_callback.WaitForResult()); - EXPECT_FALSE(stream.IsInMemory()); - EXPECT_EQ(kFakeSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + EXPECT_FALSE(stream->IsInMemory()); + EXPECT_EQ(kFakeSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); uint64 read_counter = 0; scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { + while (!stream->IsEOF()) { TestCompletionCallback read_callback; ASSERT_EQ( ERR_IO_PENDING, - stream.Read(buf.get(), kTestBufferSize, read_callback.callback())); + stream->Read(buf.get(), kTestBufferSize, read_callback.callback())); int bytes_read = read_callback.WaitForResult(); ASSERT_LE(0, bytes_read); // Not an error. read_counter += bytes_read; - EXPECT_EQ(read_counter, stream.position()); + EXPECT_EQ(read_counter, stream->position()); } // UpdateDataStream will pad out the file with 0 bytes so that the HTTP // transaction doesn't hang. Therefore we expected the full size. EXPECT_EQ(kFakeSize, read_counter); - EXPECT_EQ(read_counter, stream.position()); + EXPECT_EQ(read_counter, stream->position()); } -TEST_F(UploadDataStreamTest, ReadErrorSync) { +TEST_F(ElementsUploadDataStreamTest, ReadErrorSync) { // This element cannot be read. MockUploadElementReader* reader = new MockUploadElementReader(kTestDataSize, true); @@ -259,13 +264,14 @@ TEST_F(UploadDataStreamTest, ReadErrorSync) { element_readers_.push_back(new UploadBytesElementReader( kTestData, kTestDataSize)); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_EQ(kTestDataSize*2, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + ASSERT_EQ(OK, stream->Init(CompletionCallback())); + EXPECT_EQ(kTestDataSize*2, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); // Prepare a buffer filled with non-zero data. scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); @@ -273,16 +279,16 @@ TEST_F(UploadDataStreamTest, ReadErrorSync) { // Read() results in success even when the reader returns error. EXPECT_EQ(static_cast<int>(kTestDataSize * 2), - stream.Read(buf.get(), kTestBufferSize, CompletionCallback())); - EXPECT_EQ(kTestDataSize * 2, stream.position()); - EXPECT_TRUE(stream.IsEOF()); + stream->Read(buf.get(), kTestBufferSize, CompletionCallback())); + EXPECT_EQ(kTestDataSize * 2, stream->position()); + EXPECT_TRUE(stream->IsEOF()); // The buffer is filled with zero. EXPECT_EQ(static_cast<int>(kTestDataSize*2), std::count(buf->data(), buf->data() + kTestBufferSize, 0)); } -TEST_F(UploadDataStreamTest, ReadErrorAsync) { +TEST_F(ElementsUploadDataStreamTest, ReadErrorAsync) { // This element cannot be read. MockUploadElementReader* reader = new MockUploadElementReader(kTestDataSize, false); @@ -294,15 +300,16 @@ TEST_F(UploadDataStreamTest, ReadErrorAsync) { element_readers_.push_back(new UploadBytesElementReader( kTestData, kTestDataSize)); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback init_callback; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); EXPECT_EQ(OK, init_callback.WaitForResult()); - EXPECT_EQ(kTestDataSize*2, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); // Prepare a buffer filled with non-zero data. scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); @@ -311,17 +318,17 @@ TEST_F(UploadDataStreamTest, ReadErrorAsync) { // Read() results in success even when the reader returns error. TestCompletionCallback read_callback; ASSERT_EQ(ERR_IO_PENDING, - stream.Read(buf.get(), kTestBufferSize, read_callback.callback())); + stream->Read(buf.get(), kTestBufferSize, read_callback.callback())); EXPECT_EQ(static_cast<int>(kTestDataSize * 2), read_callback.WaitForResult()); - EXPECT_EQ(kTestDataSize*2, stream.position()); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->position()); + EXPECT_TRUE(stream->IsEOF()); // The buffer is filled with zero. EXPECT_EQ(static_cast<int>(kTestDataSize*2), std::count(buf->data(), buf->data() + kTestBufferSize, 0)); } -TEST_F(UploadDataStreamTest, FileAndBytes) { +TEST_F(ElementsUploadDataStreamTest, FileAndBytes) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -342,49 +349,29 @@ TEST_F(UploadDataStreamTest, FileAndBytes) { const uint64 kStreamSize = kTestDataSize + kFileRangeLength; TestCompletionCallback init_callback; - UploadDataStream stream(element_readers_.Pass(), 0); - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); ASSERT_EQ(OK, init_callback.WaitForResult()); - EXPECT_FALSE(stream.IsInMemory()); - EXPECT_EQ(kStreamSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + EXPECT_FALSE(stream->IsInMemory()); + EXPECT_EQ(kStreamSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { + while (!stream->IsEOF()) { TestCompletionCallback read_callback; const int result = - stream.Read(buf.get(), kTestBufferSize, read_callback.callback()); + stream->Read(buf.get(), kTestBufferSize, read_callback.callback()); const int bytes_read = result != ERR_IO_PENDING ? result : read_callback.WaitForResult(); ASSERT_LE(0, bytes_read); // Not an error. } - EXPECT_EQ(kStreamSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); -} - -TEST_F(UploadDataStreamTest, Chunk) { - const uint64 kStreamSize = kTestDataSize*2; - UploadDataStream stream(UploadDataStream::CHUNKED, 0); - stream.AppendChunk(kTestData, kTestDataSize, false); - stream.AppendChunk(kTestData, kTestDataSize, true); - - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_FALSE(stream.IsInMemory()); - EXPECT_EQ(0U, stream.size()); // Content-Length is 0 for chunked data. - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); - scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); - while (!stream.IsEOF()) { - int bytes_read = - stream.Read(buf.get(), kTestBufferSize, CompletionCallback()); - ASSERT_LE(0, bytes_read); // Not an error. - } - EXPECT_EQ(kStreamSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); + EXPECT_EQ(kStreamSize, stream->position()); + ASSERT_TRUE(stream->IsEOF()); } // Init() with on-memory and not-on-memory readers. -TEST_F(UploadDataStreamTest, InitAsync) { +TEST_F(ElementsUploadDataStreamTest, InitAsync) { // Create UploadDataStream with mock readers. MockUploadElementReader* reader = NULL; @@ -408,16 +395,17 @@ TEST_F(UploadDataStreamTest, InitAsync) { EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK)); element_readers_.push_back(reader); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback callback; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(callback.callback())); EXPECT_EQ(OK, callback.WaitForResult()); } // Init() of a reader fails asynchronously. -TEST_F(UploadDataStreamTest, InitAsyncFailureAsync) { +TEST_F(ElementsUploadDataStreamTest, InitAsyncFailureAsync) { // Create UploadDataStream with a mock reader. MockUploadElementReader* reader = NULL; @@ -425,16 +413,17 @@ TEST_F(UploadDataStreamTest, InitAsyncFailureAsync) { reader->SetAsyncInitExpectation(ERR_FAILED); element_readers_.push_back(reader); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback callback; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(callback.callback())); EXPECT_EQ(ERR_FAILED, callback.WaitForResult()); } // Init() of a reader fails synchronously. -TEST_F(UploadDataStreamTest, InitAsyncFailureSync) { +TEST_F(ElementsUploadDataStreamTest, InitAsyncFailureSync) { // Create UploadDataStream with mock readers. MockUploadElementReader* reader = NULL; @@ -446,34 +435,36 @@ TEST_F(UploadDataStreamTest, InitAsyncFailureSync) { EXPECT_CALL(*reader, Init(_)).WillOnce(Return(ERR_FAILED)); element_readers_.push_back(reader); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback callback; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(callback.callback())); EXPECT_EQ(ERR_FAILED, callback.WaitForResult()); } // Read with a buffer whose size is same as the data. -TEST_F(UploadDataStreamTest, ReadAsyncWithExactSizeBuffer) { +TEST_F(ElementsUploadDataStreamTest, ReadAsyncWithExactSizeBuffer) { element_readers_.push_back(new UploadBytesElementReader( kTestData, kTestDataSize)); - UploadDataStream stream(element_readers_.Pass(), 0); - - ASSERT_EQ(OK, stream.Init(CompletionCallback())); - EXPECT_TRUE(stream.IsInMemory()); - EXPECT_EQ(kTestDataSize, stream.size()); - EXPECT_EQ(0U, stream.position()); - EXPECT_FALSE(stream.IsEOF()); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); + + ASSERT_EQ(OK, stream->Init(CompletionCallback())); + EXPECT_TRUE(stream->IsInMemory()); + EXPECT_EQ(kTestDataSize, stream->size()); + EXPECT_EQ(0U, stream->position()); + EXPECT_FALSE(stream->IsEOF()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestDataSize); - int bytes_read = stream.Read(buf.get(), kTestDataSize, CompletionCallback()); + int bytes_read = stream->Read(buf.get(), kTestDataSize, CompletionCallback()); ASSERT_EQ(static_cast<int>(kTestDataSize), bytes_read); // Not an error. - EXPECT_EQ(kTestDataSize, stream.position()); - ASSERT_TRUE(stream.IsEOF()); + EXPECT_EQ(kTestDataSize, stream->position()); + ASSERT_TRUE(stream->IsEOF()); } // Async Read() with on-memory and not-on-memory readers. -TEST_F(UploadDataStreamTest, ReadAsync) { +TEST_F(ElementsUploadDataStreamTest, ReadAsync) { // Create UploadDataStream with mock readers. MockUploadElementReader* reader = NULL; @@ -497,11 +488,12 @@ TEST_F(UploadDataStreamTest, ReadAsync) { reader->SetReadExpectation(kTestDataSize); element_readers_.push_back(reader); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); // Run Init(). TestCompletionCallback init_callback; - EXPECT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + EXPECT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); EXPECT_EQ(OK, init_callback.WaitForResult()); scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize); @@ -509,28 +501,29 @@ TEST_F(UploadDataStreamTest, ReadAsync) { // Consume the first element. TestCompletionCallback read_callback1; EXPECT_EQ(static_cast<int>(kTestDataSize), - stream.Read(buf.get(), kTestDataSize, read_callback1.callback())); + stream->Read(buf.get(), kTestDataSize, read_callback1.callback())); base::MessageLoop::current()->RunUntilIdle(); EXPECT_FALSE(read_callback1.have_result()); // Consume the second element. TestCompletionCallback read_callback2; ASSERT_EQ(ERR_IO_PENDING, - stream.Read(buf.get(), kTestDataSize, read_callback2.callback())); + stream->Read(buf.get(), kTestDataSize, read_callback2.callback())); EXPECT_EQ(static_cast<int>(kTestDataSize), read_callback2.WaitForResult()); // Consume the third and the fourth elements. TestCompletionCallback read_callback3; ASSERT_EQ( ERR_IO_PENDING, - stream.Read(buf.get(), kTestDataSize * 2, read_callback3.callback())); + stream->Read(buf.get(), kTestDataSize * 2, read_callback3.callback())); EXPECT_EQ(static_cast<int>(kTestDataSize * 2), read_callback3.WaitForResult()); } -void UploadDataStreamTest::FileChangedHelper(const base::FilePath& file_path, - const base::Time& time, - bool error_expected) { +void ElementsUploadDataStreamTest::FileChangedHelper( + const base::FilePath& file_path, + const base::Time& time, + bool error_expected) { // Don't use element_readers_ here, as this function is called twice, and // reusing element_readers_ is wrong. ScopedVector<UploadElementReader> element_readers; @@ -538,8 +531,9 @@ void UploadDataStreamTest::FileChangedHelper(const base::FilePath& file_path, base::MessageLoopProxy::current().get(), file_path, 1, 2, time)); TestCompletionCallback init_callback; - UploadDataStream stream(element_readers.Pass(), 0); - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback())); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers.Pass(), 0)); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback.callback())); int error_code = init_callback.WaitForResult(); if (error_expected) ASSERT_EQ(ERR_UPLOAD_FILE_CHANGED, error_code); @@ -547,7 +541,7 @@ void UploadDataStreamTest::FileChangedHelper(const base::FilePath& file_path, ASSERT_EQ(OK, error_code); } -TEST_F(UploadDataStreamTest, FileChanged) { +TEST_F(ElementsUploadDataStreamTest, FileChanged) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -566,7 +560,7 @@ TEST_F(UploadDataStreamTest, FileChanged) { true); } -TEST_F(UploadDataStreamTest, MultipleInit) { +TEST_F(ElementsUploadDataStreamTest, MultipleInit) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -582,35 +576,36 @@ TEST_F(UploadDataStreamTest, MultipleInit) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::string expected_data(kTestData, kTestData + kTestDataSize); expected_data += expected_data; // Call Init(). TestCompletionCallback init_callback1; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback1.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback1.callback())); ASSERT_EQ(OK, init_callback1.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. - EXPECT_EQ(expected_data, ReadFromUploadDataStream(&stream)); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get())); + EXPECT_TRUE(stream->IsEOF()); // Call Init() again to reset. TestCompletionCallback init_callback2; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback2.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback2.callback())); ASSERT_EQ(OK, init_callback2.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read again. - EXPECT_EQ(expected_data, ReadFromUploadDataStream(&stream)); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get())); + EXPECT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, MultipleInitAsync) { +TEST_F(ElementsUploadDataStreamTest, MultipleInitAsync) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -627,33 +622,34 @@ TEST_F(UploadDataStreamTest, MultipleInitAsync) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::string expected_data(kTestData, kTestData + kTestDataSize); expected_data += expected_data; // Call Init(). - ASSERT_EQ(ERR_IO_PENDING, stream.Init(test_callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(test_callback.callback())); EXPECT_EQ(OK, test_callback.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. - EXPECT_EQ(expected_data, ReadFromUploadDataStream(&stream)); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get())); + EXPECT_TRUE(stream->IsEOF()); // Call Init() again to reset. - ASSERT_EQ(ERR_IO_PENDING, stream.Init(test_callback.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(test_callback.callback())); EXPECT_EQ(OK, test_callback.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read again. - EXPECT_EQ(expected_data, ReadFromUploadDataStream(&stream)); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_EQ(expected_data, ReadFromUploadDataStream(stream.get())); + EXPECT_TRUE(stream->IsEOF()); } -TEST_F(UploadDataStreamTest, InitToReset) { +TEST_F(ElementsUploadDataStreamTest, InitToReset) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -669,7 +665,8 @@ TEST_F(UploadDataStreamTest, InitToReset) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::vector<char> expected_data(kTestData, kTestData + kTestDataSize); expected_data.insert(expected_data.end(), expected_data.begin(), @@ -677,10 +674,10 @@ TEST_F(UploadDataStreamTest, InitToReset) { // Call Init(). TestCompletionCallback init_callback1; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback1.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback1.callback())); EXPECT_EQ(OK, init_callback1.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read some. TestCompletionCallback read_callback1; @@ -688,29 +685,30 @@ TEST_F(UploadDataStreamTest, InitToReset) { scoped_refptr<IOBuffer> wrapped_buffer = new WrappedIOBuffer(&buf[0]); EXPECT_EQ( ERR_IO_PENDING, - stream.Read(wrapped_buffer.get(), buf.size(), read_callback1.callback())); + stream->Read(wrapped_buffer.get(), buf.size(), + read_callback1.callback())); EXPECT_EQ(static_cast<int>(buf.size()), read_callback1.WaitForResult()); - EXPECT_EQ(buf.size(), stream.position()); + EXPECT_EQ(buf.size(), stream->position()); // Call Init to reset the state. TestCompletionCallback init_callback2; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback2.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback2.callback())); EXPECT_EQ(OK, init_callback2.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. TestCompletionCallback read_callback2; std::vector<char> buf2(kTestDataSize*2); scoped_refptr<IOBuffer> wrapped_buffer2 = new WrappedIOBuffer(&buf2[0]); EXPECT_EQ(ERR_IO_PENDING, - stream.Read( + stream->Read( wrapped_buffer2.get(), buf2.size(), read_callback2.callback())); EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult()); EXPECT_EQ(expected_data, buf2); } -TEST_F(UploadDataStreamTest, InitDuringAsyncInit) { +TEST_F(ElementsUploadDataStreamTest, InitDuringAsyncInit) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -726,7 +724,8 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncInit) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::vector<char> expected_data(kTestData, kTestData + kTestDataSize); expected_data.insert(expected_data.end(), expected_data.begin(), @@ -734,31 +733,31 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncInit) { // Start Init. TestCompletionCallback init_callback1; - EXPECT_EQ(ERR_IO_PENDING, stream.Init(init_callback1.callback())); + EXPECT_EQ(ERR_IO_PENDING, stream->Init(init_callback1.callback())); // Call Init again to cancel the previous init. TestCompletionCallback init_callback2; - EXPECT_EQ(ERR_IO_PENDING, stream.Init(init_callback2.callback())); + EXPECT_EQ(ERR_IO_PENDING, stream->Init(init_callback2.callback())); EXPECT_EQ(OK, init_callback2.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. TestCompletionCallback read_callback2; std::vector<char> buf2(kTestDataSize*2); scoped_refptr<IOBuffer> wrapped_buffer2 = new WrappedIOBuffer(&buf2[0]); EXPECT_EQ(ERR_IO_PENDING, - stream.Read( + stream->Read( wrapped_buffer2.get(), buf2.size(), read_callback2.callback())); EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult()); EXPECT_EQ(expected_data, buf2); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_TRUE(stream->IsEOF()); // Make sure callbacks are not called for cancelled operations. EXPECT_FALSE(init_callback1.have_result()); } -TEST_F(UploadDataStreamTest, InitDuringAsyncRead) { +TEST_F(ElementsUploadDataStreamTest, InitDuringAsyncRead) { base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file_path)); @@ -774,7 +773,8 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncRead) { 0, kuint64max, base::Time())); - UploadDataStream stream(element_readers_.Pass(), 0); + scoped_ptr<UploadDataStream> stream( + new ElementsUploadDataStream(element_readers_.Pass(), 0)); std::vector<char> expected_data(kTestData, kTestData + kTestDataSize); expected_data.insert(expected_data.end(), expected_data.begin(), @@ -782,10 +782,10 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncRead) { // Call Init(). TestCompletionCallback init_callback1; - ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback1.callback())); + ASSERT_EQ(ERR_IO_PENDING, stream->Init(init_callback1.callback())); EXPECT_EQ(OK, init_callback1.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Start reading. TestCompletionCallback read_callback1; @@ -793,25 +793,26 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncRead) { scoped_refptr<IOBuffer> wrapped_buffer = new WrappedIOBuffer(&buf[0]); EXPECT_EQ( ERR_IO_PENDING, - stream.Read(wrapped_buffer.get(), buf.size(), read_callback1.callback())); + stream->Read(wrapped_buffer.get(), buf.size(), + read_callback1.callback())); // Call Init to cancel the previous read. TestCompletionCallback init_callback2; - EXPECT_EQ(ERR_IO_PENDING, stream.Init(init_callback2.callback())); + EXPECT_EQ(ERR_IO_PENDING, stream->Init(init_callback2.callback())); EXPECT_EQ(OK, init_callback2.WaitForResult()); - EXPECT_FALSE(stream.IsEOF()); - EXPECT_EQ(kTestDataSize*2, stream.size()); + EXPECT_FALSE(stream->IsEOF()); + EXPECT_EQ(kTestDataSize*2, stream->size()); // Read. TestCompletionCallback read_callback2; std::vector<char> buf2(kTestDataSize*2); scoped_refptr<IOBuffer> wrapped_buffer2 = new WrappedIOBuffer(&buf2[0]); EXPECT_EQ(ERR_IO_PENDING, - stream.Read( + stream->Read( wrapped_buffer2.get(), buf2.size(), read_callback2.callback())); EXPECT_EQ(static_cast<int>(buf2.size()), read_callback2.WaitForResult()); EXPECT_EQ(expected_data, buf2); - EXPECT_TRUE(stream.IsEOF()); + EXPECT_TRUE(stream->IsEOF()); // Make sure callbacks are not called for cancelled operations. EXPECT_FALSE(read_callback1.have_result()); diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc index 785d5e9..936c912 100644 --- a/net/base/upload_data_stream.cc +++ b/net/base/upload_data_stream.cc @@ -4,261 +4,125 @@ #include "net/base/upload_data_stream.h" +#include "base/callback_helpers.h" #include "base/logging.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" -#include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_element_reader.h" namespace net { -UploadDataStream::UploadDataStream( - ScopedVector<UploadElementReader> element_readers, - int64 identifier) - : element_readers_(element_readers.Pass()), - element_index_(0), - total_size_(0), +UploadDataStream::UploadDataStream(bool is_chunked, int64 identifier) + : total_size_(0), current_position_(0), identifier_(identifier), - is_chunked_(false), - last_chunk_appended_(false), - read_failed_(false), + is_chunked_(is_chunked), initialized_successfully_(false), - weak_ptr_factory_(this) { -} - -UploadDataStream::UploadDataStream(Chunked /*chunked*/, int64 identifier) - : element_index_(0), - total_size_(0), - current_position_(0), - identifier_(identifier), - is_chunked_(true), - last_chunk_appended_(false), - read_failed_(false), - initialized_successfully_(false), - weak_ptr_factory_(this) { + is_eof_(false) { } UploadDataStream::~UploadDataStream() { } -UploadDataStream* UploadDataStream::CreateWithReader( - scoped_ptr<UploadElementReader> reader, - int64 identifier) { - ScopedVector<UploadElementReader> readers; - readers.push_back(reader.release()); - return new UploadDataStream(readers.Pass(), identifier); -} - int UploadDataStream::Init(const CompletionCallback& callback) { Reset(); - return InitInternal(0, callback); + DCHECK(!initialized_successfully_); + DCHECK(callback_.is_null()); + DCHECK(!callback.is_null() || IsInMemory()); + int result = InitInternal(); + if (result == ERR_IO_PENDING) { + DCHECK(!IsInMemory()); + callback_ = callback; + } else { + OnInitCompleted(result); + } + return result; } int UploadDataStream::Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { + DCHECK(!callback.is_null() || IsInMemory()); DCHECK(initialized_successfully_); DCHECK_GT(buf_len, 0); - return ReadInternal(new DrainableIOBuffer(buf, buf_len), callback); + if (is_eof_) + return 0; + int result = ReadInternal(buf, buf_len); + if (result == ERR_IO_PENDING) { + DCHECK(!IsInMemory()); + callback_ = callback; + } else { + OnReadCompleted(result); + } + return result; } bool UploadDataStream::IsEOF() const { DCHECK(initialized_successfully_); - if (!is_chunked_) - return current_position_ == total_size_; - - // If the upload data is chunked, check if the last chunk is appended and all - // elements are consumed. - return element_index_ == element_readers_.size() && last_chunk_appended_; -} - -bool UploadDataStream::IsInMemory() const { - // Chunks are in memory, but UploadData does not have all the chunks at - // once. Chunks are provided progressively with AppendChunk() as chunks - // are ready. Check is_chunked_ here, rather than relying on the loop - // below, as there is a case that is_chunked_ is set to true, but the - // first chunk is not yet delivered. - if (is_chunked_) - return false; - - for (size_t i = 0; i < element_readers_.size(); ++i) { - if (!element_readers_[i]->IsInMemory()) - return false; - } - return true; -} - -void UploadDataStream::AppendChunk(const char* bytes, - int bytes_len, - bool is_last_chunk) { - DCHECK(is_chunked_); - DCHECK(!last_chunk_appended_); - last_chunk_appended_ = is_last_chunk; - - // Initialize a reader for the newly appended chunk. We leave |total_size_| at - // zero, since for chunked uploads, we may not know the total size. - std::vector<char> data(bytes, bytes + bytes_len); - UploadElementReader* reader = new UploadOwnedBytesElementReader(&data); - const int rv = reader->Init(net::CompletionCallback()); - DCHECK_EQ(OK, rv); - element_readers_.push_back(reader); - - // Resume pending read. - if (!pending_chunked_read_callback_.is_null()) { - base::Closure callback = pending_chunked_read_callback_; - pending_chunked_read_callback_.Reset(); - callback.Run(); - } + DCHECK(is_chunked_ || is_eof_ == (current_position_ == total_size_)); + return is_eof_; } void UploadDataStream::Reset() { - weak_ptr_factory_.InvalidateWeakPtrs(); - pending_chunked_read_callback_.Reset(); - initialized_successfully_ = false; - read_failed_ = false; current_position_ = 0; + initialized_successfully_ = false; + is_eof_ = false; total_size_ = 0; - element_index_ = 0; + callback_.Reset(); + ResetInternal(); } -int UploadDataStream::InitInternal(int start_index, - const CompletionCallback& callback) { +void UploadDataStream::SetSize(uint64 size) { DCHECK(!initialized_successfully_); + DCHECK(!is_chunked_); + total_size_ = size; +} - // Call Init() for all elements. - for (size_t i = start_index; i < element_readers_.size(); ++i) { - UploadElementReader* reader = element_readers_[i]; - // When new_result is ERR_IO_PENDING, InitInternal() will be called - // with start_index == i + 1 when reader->Init() finishes. - const int result = reader->Init( - base::Bind(&UploadDataStream::ResumePendingInit, - weak_ptr_factory_.GetWeakPtr(), - i + 1, - callback)); - if (result != OK) { - DCHECK(result != ERR_IO_PENDING || !callback.is_null()); - return result; - } - } +void UploadDataStream::SetIsFinalChunk() { + DCHECK(initialized_successfully_); + DCHECK(is_chunked_); + DCHECK(!is_eof_); + is_eof_ = true; +} - // Finalize initialization. - if (!is_chunked_) { - uint64 total_size = 0; - for (size_t i = 0; i < element_readers_.size(); ++i) { - UploadElementReader* reader = element_readers_[i]; - total_size += reader->GetContentLength(); - } - total_size_ = total_size; - } - initialized_successfully_ = true; - return OK; +bool UploadDataStream::IsInMemory() const { + return false; +} + +const ScopedVector<UploadElementReader>* +UploadDataStream::GetElementReaders() const { + return NULL; } -void UploadDataStream::ResumePendingInit(int start_index, - const CompletionCallback& callback, - int previous_result) { +void UploadDataStream::OnInitCompleted(int result) { + DCHECK_NE(ERR_IO_PENDING, result); DCHECK(!initialized_successfully_); - DCHECK(!callback.is_null()); - DCHECK_NE(ERR_IO_PENDING, previous_result); + DCHECK_EQ(0u, current_position_); + DCHECK(!is_eof_); - // Check the last result. - if (previous_result != OK) { - callback.Run(previous_result); - return; + if (result == OK) { + initialized_successfully_ = true; + if (!is_chunked_ && total_size_ == 0) + is_eof_ = true; } - - const int result = InitInternal(start_index, callback); - if (result != ERR_IO_PENDING) - callback.Run(result); + if (!callback_.is_null()) + base::ResetAndReturn(&callback_).Run(result); } -int UploadDataStream::ReadInternal(scoped_refptr<DrainableIOBuffer> buf, - const CompletionCallback& callback) { +void UploadDataStream::OnReadCompleted(int result) { + DCHECK_GE(result, 0); DCHECK(initialized_successfully_); - while (!read_failed_ && element_index_ < element_readers_.size()) { - UploadElementReader* reader = element_readers_[element_index_]; - - if (reader->BytesRemaining() == 0) { - ++element_index_; - continue; - } - - if (buf->BytesRemaining() == 0) - break; - - int result = reader->Read( - buf.get(), - buf->BytesRemaining(), - base::Bind(base::IgnoreResult(&UploadDataStream::ResumePendingRead), - weak_ptr_factory_.GetWeakPtr(), - buf, - callback)); - if (result == ERR_IO_PENDING) { - DCHECK(!callback.is_null()); - return ERR_IO_PENDING; - } - ProcessReadResult(buf, result); - } - - if (read_failed_) { - // Chunked transfers may only contain byte readers, so cannot have read - // failures. - DCHECK(!is_chunked_); - - // If an error occured during read operation, then pad with zero. - // Otherwise the server will hang waiting for the rest of the data. - const int num_bytes_to_fill = - std::min(static_cast<uint64>(buf->BytesRemaining()), - size() - position() - buf->BytesConsumed()); - DCHECK_LE(0, num_bytes_to_fill); - memset(buf->data(), 0, num_bytes_to_fill); - buf->DidConsume(num_bytes_to_fill); - } - - const int bytes_copied = buf->BytesConsumed(); - current_position_ += bytes_copied; - DCHECK(is_chunked_ || total_size_ >= current_position_); - - if (is_chunked_ && !IsEOF() && bytes_copied == 0) { - DCHECK(!callback.is_null()); - DCHECK(pending_chunked_read_callback_.is_null()); - pending_chunked_read_callback_ = - base::Bind(&UploadDataStream::ResumePendingRead, - weak_ptr_factory_.GetWeakPtr(), - buf, - callback, - OK); - return ERR_IO_PENDING; + current_position_ += result; + if (!is_chunked_) { + DCHECK_LE(current_position_, total_size_); + if (current_position_ == total_size_) + is_eof_ = true; } - // Returning 0 is allowed only when IsEOF() == true. - DCHECK(bytes_copied != 0 || IsEOF()); - return bytes_copied; -} - -void UploadDataStream::ResumePendingRead(scoped_refptr<DrainableIOBuffer> buf, - const CompletionCallback& callback, - int previous_result) { - DCHECK(!callback.is_null()); - - ProcessReadResult(buf, previous_result); - - const int result = ReadInternal(buf, callback); - if (result != ERR_IO_PENDING) - callback.Run(result); -} - -void UploadDataStream::ProcessReadResult(scoped_refptr<DrainableIOBuffer> buf, - int result) { - DCHECK_NE(ERR_IO_PENDING, result); - DCHECK(!read_failed_); + DCHECK(result > 0 || is_eof_); - if (result >= 0) - buf->DidConsume(result); - else - read_failed_ = true; + if (!callback_.is_null()) + base::ResetAndReturn(&callback_).Run(result); } } // namespace net diff --git a/net/base/upload_data_stream.h b/net/base/upload_data_stream.h index ac14e38..d7df8c9 100644 --- a/net/base/upload_data_stream.h +++ b/net/base/upload_data_stream.h @@ -5,10 +5,9 @@ #ifndef NET_BASE_UPLOAD_DATA_STREAM_H_ #define NET_BASE_UPLOAD_DATA_STREAM_H_ -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" +#include "base/basictypes.h" +#include "base/macros.h" #include "base/memory/scoped_vector.h" -#include "base/memory/weak_ptr.h" #include "net/base/completion_callback.h" #include "net/base/net_export.h" @@ -18,31 +17,22 @@ class DrainableIOBuffer; class IOBuffer; class UploadElementReader; -// A class to read all elements from an UploadData object. +// A class for retrieving all data to be sent as a request body. Supports both +// chunked and non-chunked uploads. class NET_EXPORT UploadDataStream { public: - // An enum used to construct chunked data stream. - enum Chunked { CHUNKED }; + // |identifier| identifies a particular upload instance, which is used by the + // cache to formulate a cache key. This value should be unique across browser + // sessions. A value of 0 is used to indicate an unspecified identifier. + UploadDataStream(bool is_chunked, int64 identifier); - // Constructs a non-chunked data stream. - UploadDataStream(ScopedVector<UploadElementReader> element_readers, - int64 identifier); - - // Constructs a chunked data stream. - UploadDataStream(Chunked chunked, int64 identifier); - - ~UploadDataStream(); - - // Creates UploadDataStream with a reader. - static UploadDataStream* CreateWithReader( - scoped_ptr<UploadElementReader> reader, - int64 identifier); + virtual ~UploadDataStream(); // Initializes the stream. This function must be called before calling any // other method. It is not valid to call any method (other than the - // destructor) if Init() returns a failure. This method can be called multiple - // times. Calling this method after a Init() success results in resetting the - // state. + // destructor) if Init() fails. This method can be called multiple times. + // Calling this method after an Init() success results in resetting the + // state (i.e. the stream is rewound). // // Does the initialization synchronously and returns the result if possible, // otherwise returns ERR_IO_PENDING and runs the callback with the result. @@ -62,93 +52,88 @@ class NET_EXPORT UploadDataStream { // If there's less data to read than we initially observed (i.e. the actual // upload data is smaller than size()), zeros are padded to ensure that // size() bytes can be read, which can happen for TYPE_FILE payloads. + // + // Reads are currently not allowed to fail - they must either return + // a value >= 0 or ERR_IO_PENDING, and call OnReadCompleted with a + // value >= 0. + // TODO(mmenke): Investigate letting reads fail. int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback); - // Identifies a particular upload instance, which is used by the cache to - // formulate a cache key. This value should be unique across browser - // sessions. A value of 0 is used to indicate an unspecified identifier. - int64 identifier() const { return identifier_; } - // Returns the total size of the data stream and the current position. - // size() is not to be used to determine whether the stream has ended - // because it is possible for the stream to end before its size is reached, - // for example, if the file is truncated. When the data is chunked, size() - // always returns zero. + // When the data is chunked, always returns zero. Must always return the same + // value after each call to Initialize(). uint64 size() const { return total_size_; } uint64 position() const { return current_position_; } - bool is_chunked() const { return is_chunked_; } - bool last_chunk_appended() const { return last_chunk_appended_; } + // See constructor for description. + int64 identifier() const { return identifier_; } - const ScopedVector<UploadElementReader>& element_readers() const { - return element_readers_; - } + bool is_chunked() const { return is_chunked_; } // Returns true if all data has been consumed from this upload data - // stream. + // stream. For chunked uploads, returns false until the first read attempt. + // This makes some state machines a little simpler. bool IsEOF() const; - // Returns true if the upload data in the stream is entirely in memory. - bool IsInMemory() const; + // Cancels all pending callbacks, and resets state. Any IOBuffer currently + // being read to is not safe for future use, as it may be in use on another + // thread. + void Reset(); + + // Returns true if the upload data in the stream is entirely in memory, and + // all read requests will succeed synchronously. Expected to return false for + // chunked requests. + virtual bool IsInMemory() const; - // Adds the given chunk of bytes to be sent with chunked transfer encoding. - void AppendChunk(const char* bytes, int bytes_len, bool is_last_chunk); + // Returns a list of element readers owned by |this|, if it has any. + virtual const ScopedVector<UploadElementReader>* + GetElementReaders() const; - // Resets this instance to the uninitialized state. - void Reset(); + protected: + // Must be called by subclasses when InitInternal and ReadInternal complete + // asynchronously. + void OnInitCompleted(int result); + void OnReadCompleted(int result); + + // Must be called before InitInternal completes, for non-chunked uploads. + // Must not be called for chunked uploads. + void SetSize(uint64 size); + + // Must be called for chunked uploads before the final ReadInternal call + // completes. Must not be called for non-chunked uploads. + void SetIsFinalChunk(); private: - // Runs Init() for all element readers. - // This method is used to implement Init(). - int InitInternal(int start_index, const CompletionCallback& callback); - - // Resumes initialization and runs callback with the result when necessary. - void ResumePendingInit(int start_index, - const CompletionCallback& callback, - int previous_result); - - // Reads data from the element readers. - // This method is used to implement Read(). - int ReadInternal(scoped_refptr<DrainableIOBuffer> buf, - const CompletionCallback& callback); - - // Resumes pending read and calls callback with the result when necessary. - void ResumePendingRead(scoped_refptr<DrainableIOBuffer> buf, - const CompletionCallback& callback, - int previous_result); - - // Processes result of UploadElementReader::Read(). If |result| indicates - // success, updates |buf|'s offset. Otherwise, sets |read_failed_| to true. - void ProcessReadResult(scoped_refptr<DrainableIOBuffer> buf, - int result); - - ScopedVector<UploadElementReader> element_readers_; - - // Index of the current upload element (i.e. the element currently being - // read). The index is used as a cursor to iterate over elements in - // |upload_data_|. - size_t element_index_; - - // Size and current read position within the upload data stream. - // |total_size_| is set to zero when the data is chunked. + // See Init(). If it returns ERR_IO_PENDING, OnInitCompleted must be called + // once it completes. If the upload is not chunked, SetSize must be called + // before it completes. + virtual int InitInternal() = 0; + + // See Read(). For chunked uploads, must call SetIsFinalChunk if this is the + // final chunk. For non-chunked uploads, the UploadDataStream determins which + // read is the last based on size. Must read 1 or more bytes on every call, + // though the final chunk may be 0 bytes, for chunked requests. If it returns + // ERR_IO_PENDING, OnInitCompleted must be called once it completes. Must not + // return any error, other than ERR_IO_PENDING. + virtual int ReadInternal(IOBuffer* buf, int buf_len) = 0; + + // Resets state and cancels any pending callbacks. Guaranteed to be called + // before all but the first call to InitInternal. + virtual void ResetInternal() = 0; + uint64 total_size_; uint64 current_position_; const int64 identifier_; const bool is_chunked_; - bool last_chunk_appended_; - - // True if an error occcured during read operation. - bool read_failed_; // True if the initialization was successful. bool initialized_successfully_; - // Callback to resume reading chunked data. - base::Closure pending_chunked_read_callback_; + bool is_eof_; - base::WeakPtrFactory<UploadDataStream> weak_ptr_factory_; + CompletionCallback callback_; DISALLOW_COPY_AND_ASSIGN(UploadDataStream); }; diff --git a/net/base/upload_element_reader.h b/net/base/upload_element_reader.h index d71f57c..a46b970 100644 --- a/net/base/upload_element_reader.h +++ b/net/base/upload_element_reader.h @@ -35,8 +35,8 @@ class NET_EXPORT UploadElementReader { // state. virtual int Init(const CompletionCallback& callback) = 0; - // Returns the byte-length of the element. For files that do not exist, 0 - // is returned. This is done for consistency with Mozilla. + // Returns the byte-length of the element. For files that do not exist, 0 + // is returned. This is done for consistency with Mozilla. virtual uint64 GetContentLength() const = 0; // Returns the number of bytes remaining to read. diff --git a/net/base/upload_file_element_reader.h b/net/base/upload_file_element_reader.h index 868f804..dc27585 100644 --- a/net/base/upload_file_element_reader.h +++ b/net/base/upload_file_element_reader.h @@ -51,7 +51,7 @@ class NET_EXPORT UploadFileElementReader : public UploadElementReader { const CompletionCallback& callback) override; private: - FRIEND_TEST_ALL_PREFIXES(UploadDataStreamTest, FileSmallerThanLength); + FRIEND_TEST_ALL_PREFIXES(ElementsUploadDataStreamTest, FileSmallerThanLength); FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, UploadFileSmallerThanLength); diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 8081bd7..8703b87 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc @@ -14,6 +14,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "net/base/cache_type.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/host_port_pair.h" #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" @@ -21,7 +22,6 @@ #include "net/base/net_errors.h" #include "net/base/net_log_unittest.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/cert/cert_status_flags.h" #include "net/disk_cache/disk_cache.h" #include "net/http/http_byte_range.h" @@ -2774,7 +2774,8 @@ TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Hit) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), kUploadId); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), + kUploadId); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -2805,7 +2806,8 @@ TEST(HttpCache, SimplePOST_WithRanges) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), kUploadId); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), + kUploadId); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -2824,7 +2826,7 @@ TEST(HttpCache, SimplePOST_SeparateCache) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 1); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); MockTransaction transaction(kSimplePOST_Transaction); MockHttpRequest req1(transaction); @@ -2863,7 +2865,7 @@ TEST(HttpCache, SimplePOST_Invalidate_205) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 1); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); transaction.method = "POST"; transaction.status = "HTTP/1.1 205 No Content"; @@ -2902,7 +2904,7 @@ TEST(HttpCache, SimplePOST_NoUploadId_Invalidate_205) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "POST"; transaction.status = "HTTP/1.1 205 No Content"; @@ -2933,7 +2935,7 @@ TEST(HttpCache, SimplePOST_NoUploadId_NoBackend) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); MockTransaction transaction(kSimplePOST_Transaction); AddMockTransaction(&transaction); @@ -2962,7 +2964,7 @@ TEST(HttpCache, SimplePOST_DontInvalidate_100) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 1); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); transaction.method = "POST"; transaction.status = "HTTP/1.1 100 Continue"; @@ -3273,7 +3275,7 @@ TEST(HttpCache, SimplePUT_Miss) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -3302,7 +3304,7 @@ TEST(HttpCache, SimplePUT_Invalidate) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "PUT"; MockHttpRequest req2(transaction); @@ -3338,7 +3340,7 @@ TEST(HttpCache, SimplePUT_Invalidate_305) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "PUT"; transaction.status = "HTTP/1.1 305 Use Proxy"; @@ -3376,7 +3378,7 @@ TEST(HttpCache, SimplePUT_DontInvalidate_404) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "PUT"; transaction.status = "HTTP/1.1 404 Not Found"; @@ -3406,7 +3408,7 @@ TEST(HttpCache, SimpleDELETE_Miss) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -3435,7 +3437,7 @@ TEST(HttpCache, SimpleDELETE_Invalidate) { ScopedVector<net::UploadElementReader> element_readers; element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::UploadDataStream upload_data_stream(element_readers.Pass(), 0); + net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "DELETE"; MockHttpRequest req2(transaction); diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 4b2f0a4..7531c91 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -22,7 +22,9 @@ #include "base/test/test_file_util.h" #include "net/base/auth.h" #include "net/base/capturing_net_log.h" +#include "net/base/chunked_upload_data_stream.h" #include "net/base/completion_callback.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" #include "net/base/net_log.h" @@ -31,7 +33,6 @@ #include "net/base/test_completion_callback.h" #include "net/base/test_data_directory.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" #include "net/cert/mock_cert_verifier.h" #include "net/dns/host_cache.h" @@ -1111,7 +1112,7 @@ TEST_P(HttpNetworkTransactionTest, ReuseConnection) { TEST_P(HttpNetworkTransactionTest, Ignores100) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -5016,7 +5017,7 @@ TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) { TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request[2]; // Transaction 1: a GET request that succeeds. The socket is recycled @@ -8102,7 +8103,7 @@ TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) { 0, kuint64max, base::Time())); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -8159,7 +8160,7 @@ TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) { 0, kuint64max, base::Time())); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -8217,7 +8218,7 @@ TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) { FakeUploadElementReader* fake_reader = new FakeUploadElementReader; ScopedVector<UploadElementReader> element_readers; element_readers.push_back(fake_reader); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -12731,7 +12732,7 @@ TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) { TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -12838,7 +12839,7 @@ TEST_P(HttpNetworkTransactionTest, ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request2; request2.method = "POST"; @@ -12870,7 +12871,7 @@ TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetPartialBodySent) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -12925,7 +12926,7 @@ TEST_P(HttpNetworkTransactionTest, TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0); + ChunkedUploadDataStream upload_data_stream(0); HttpRequestInfo request; request.method = "POST"; @@ -12964,7 +12965,7 @@ TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) { // the test more future proof. base::RunLoop().RunUntilIdle(); - upload_data_stream.AppendChunk("last chunk", 10, true); + upload_data_stream.AppendData("last chunk", 10, true); rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); @@ -12984,7 +12985,7 @@ TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) { TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -13037,7 +13038,7 @@ TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) { TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -13082,7 +13083,7 @@ TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterResetAnd100) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -13128,7 +13129,7 @@ TEST_P(HttpNetworkTransactionTest, TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -13171,7 +13172,7 @@ TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) { TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back(new UploadBytesElementReader("foo", 3)); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc index 38279a4..ef83638 100644 --- a/net/http/http_stream_parser_unittest.cc +++ b/net/http/http_stream_parser_unittest.cc @@ -15,11 +15,12 @@ #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" +#include "net/base/chunked_upload_data_stream.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" #include "net/http/http_request_headers.h" #include "net/http/http_request_info.h" @@ -106,7 +107,7 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_NoBody) { TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_EmptyBody) { ScopedVector<UploadElementReader> element_readers; scoped_ptr<UploadDataStream> body( - new UploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(element_readers.Pass(), 0)); ASSERT_EQ(OK, body->Init(CompletionCallback())); // Shouldn't be merged if upload data is empty. ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( @@ -115,10 +116,9 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_EmptyBody) { TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_ChunkedBody) { const std::string payload = "123"; - scoped_ptr<UploadDataStream> body( - new UploadDataStream(UploadDataStream::CHUNKED, 0)); - body->AppendChunk(payload.data(), payload.size(), true); - ASSERT_EQ(OK, body->Init(CompletionCallback())); + scoped_ptr<ChunkedUploadDataStream> body(new ChunkedUploadDataStream(0)); + body->AppendData(payload.data(), payload.size(), true); + ASSERT_EQ(OK, body->Init(TestCompletionCallback().callback())); // Shouldn't be merged if upload data carries chunked data. ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( "some header", body.get())); @@ -143,7 +143,7 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) { base::Time())); scoped_ptr<UploadDataStream> body( - new UploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(element_readers.Pass(), 0)); TestCompletionCallback callback; ASSERT_EQ(ERR_IO_PENDING, body->Init(callback.callback())); ASSERT_EQ(OK, callback.WaitForResult()); @@ -162,7 +162,7 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_SmallBodyInMemory) { payload.data(), payload.size())); scoped_ptr<UploadDataStream> body( - new UploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(element_readers.Pass(), 0)); ASSERT_EQ(OK, body->Init(CompletionCallback())); // Yes, should be merged if the in-memory body is small here. ASSERT_TRUE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( @@ -176,7 +176,7 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_LargeBodyInMemory) { payload.data(), payload.size())); scoped_ptr<UploadDataStream> body( - new UploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(element_readers.Pass(), 0)); ASSERT_EQ(OK, body->Init(CompletionCallback())); // Shouldn't be merged if the in-memory body is large here. ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( @@ -218,9 +218,9 @@ TEST(HttpStreamParser, AsyncChunkAndAsyncSocket) { MockRead(SYNCHRONOUS, 0, 8), // EOF }; - UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); - upload_stream.AppendChunk(kChunk1, arraysize(kChunk1) - 1, false); - ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); + ChunkedUploadDataStream upload_stream(0); + upload_stream.AppendData(kChunk1, arraysize(kChunk1) - 1, false); + ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); DeterministicSocketData data(reads, arraysize(reads), writes, arraysize(writes)); @@ -267,7 +267,7 @@ TEST(HttpStreamParser, AsyncChunkAndAsyncSocket) { // Now append another chunk (while the first write is still pending), which // should not confuse the state machine. - upload_stream.AppendChunk(kChunk2, arraysize(kChunk2) - 1, false); + upload_stream.AppendData(kChunk2, arraysize(kChunk2) - 1, false); ASSERT_FALSE(callback.have_result()); // Complete writing the first chunk, which should then enqueue the second @@ -284,7 +284,7 @@ TEST(HttpStreamParser, AsyncChunkAndAsyncSocket) { // Add the final chunk. This will enqueue another write, but it will not // complete due to the async nature. - upload_stream.AppendChunk(kChunk3, arraysize(kChunk3) - 1, true); + upload_stream.AppendData(kChunk3, arraysize(kChunk3) - 1, true); ASSERT_FALSE(callback.have_result()); // Finalize writing the last chunk, which will enqueue the trailer. diff --git a/net/net.gypi b/net/net.gypi index 8ed69df..36aa3e6 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -189,6 +189,8 @@ 'base/bandwidth_metrics.cc', 'base/bandwidth_metrics.h', 'base/cache_type.h', + 'base/chunked_upload_data_stream.cc', + 'base/chunked_upload_data_stream.h', 'base/crypto_module.h', 'base/crypto_module_nss.cc', 'base/crypto_module_openssl.cc', @@ -198,6 +200,8 @@ 'base/directory_lister.h', 'base/dns_reloader.cc', 'base/dns_reloader.h', + 'base/elements_upload_data_stream.cc', + 'base/elements_upload_data_stream.h', 'base/expiring_cache.h', 'base/file_stream.cc', 'base/file_stream.h', @@ -1254,9 +1258,11 @@ 'base/address_list_unittest.cc', 'base/address_tracker_linux_unittest.cc', 'base/backoff_entry_unittest.cc', + 'base/chunked_upload_data_stream_unittest.cc', 'base/data_url_unittest.cc', 'base/directory_lister_unittest.cc', 'base/dns_util_unittest.cc', + 'base/elements_upload_data_stream_unittest.cc', 'base/escape_unittest.cc', 'base/expiring_cache_unittest.cc', 'base/file_stream_unittest.cc', @@ -1285,7 +1291,6 @@ 'base/test_completion_callback_unittest.cc', 'base/trace_net_log_observer_unittest.cc', 'base/upload_bytes_element_reader_unittest.cc', - 'base/upload_data_stream_unittest.cc', 'base/upload_file_element_reader_unittest.cc', 'base/url_util_unittest.cc', 'cert/cert_verify_proc_unittest.cc', diff --git a/net/ocsp/nss_ocsp.cc b/net/ocsp/nss_ocsp.cc index 844816e..02eb2c7 100644 --- a/net/ocsp/nss_ocsp.cc +++ b/net/ocsp/nss_ocsp.cc @@ -30,12 +30,12 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/host_port_pair.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/url_request/redirect_info.h" @@ -411,8 +411,8 @@ class OCSPRequestSession scoped_ptr<UploadElementReader> reader(new UploadBytesElementReader( upload_content_.data(), upload_content_.size())); - request_->set_upload(make_scoped_ptr( - UploadDataStream::CreateWithReader(reader.Pass(), 0))); + request_->set_upload( + ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0)); } if (!extra_request_headers_.IsEmpty()) request_->SetExtraRequestHeaders(extra_request_headers_); diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc index 016b324..ad0643da 100644 --- a/net/quic/quic_end_to_end_unittest.cc +++ b/net/quic/quic_end_to_end_unittest.cc @@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/test_completion_callback.h" #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" @@ -189,7 +190,8 @@ class QuicEndToEndTest : public PlatformTest { element_readers.push_back( new UploadBytesElementReader(request_body_.data(), request_body_.length())); - upload_data_stream_.reset(new UploadDataStream(element_readers.Pass(), 0)); + upload_data_stream_.reset( + new ElementsUploadDataStream(element_readers.Pass(), 0)); request_.method = "POST"; request_.url = GURL("http://www.google.com/"); request_.upload_data_stream = upload_data_stream_.get(); diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc index 9926477..35321d9 100644 --- a/net/quic/quic_http_stream_test.cc +++ b/net/quic/quic_http_stream_test.cc @@ -6,10 +6,11 @@ #include <vector> +#include "net/base/chunked_upload_data_stream.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/http/http_response_headers.h" #include "net/http/transport_security_state.h" #include "net/quic/congestion_control/receive_algorithm_interface.h" @@ -489,7 +490,7 @@ TEST_P(QuicHttpStreamTest, SendPostRequest) { ScopedVector<UploadElementReader> element_readers; element_readers.push_back( new UploadBytesElementReader(kUploadData, strlen(kUploadData))); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); request_.method = "POST"; request_.url = GURL("http://www.google.com/"); request_.upload_data_stream = &upload_data_stream; @@ -535,20 +536,21 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) { AddWrite(ConstructAckPacket(4, 3, 1)); Initialize(); - UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0); - upload_data_stream.AppendChunk(kUploadData, chunk_size, false); + ChunkedUploadDataStream upload_data_stream(0); + upload_data_stream.AppendData(kUploadData, chunk_size, false); request_.method = "POST"; request_.url = GURL("http://www.google.com/"); request_.upload_data_stream = &upload_data_stream; - ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback())); + ASSERT_EQ(OK, request_.upload_data_stream->Init( + TestCompletionCallback().callback())); ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_, callback_.callback())); ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_, callback_.callback())); - upload_data_stream.AppendChunk(kUploadData, chunk_size, true); + upload_data_stream.AppendData(kUploadData, chunk_size, true); // Ack both packets in the request. ProcessPacket(ConstructAckPacket(1, 0, 0)); @@ -586,20 +588,21 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) { AddWrite(ConstructAckPacket(4, 3, 1)); Initialize(); - UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0); - upload_data_stream.AppendChunk(kUploadData, chunk_size, false); + ChunkedUploadDataStream upload_data_stream(0); + upload_data_stream.AppendData(kUploadData, chunk_size, false); request_.method = "POST"; request_.url = GURL("http://www.google.com/"); request_.upload_data_stream = &upload_data_stream; - ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback())); + ASSERT_EQ(OK, request_.upload_data_stream->Init( + TestCompletionCallback().callback())); ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_, callback_.callback())); ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_, callback_.callback())); - upload_data_stream.AppendChunk(nullptr, 0, true); + upload_data_stream.AppendData(nullptr, 0, true); ProcessPacket(ConstructAckPacket(1, 0, 0)); @@ -634,19 +637,20 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) { AddWrite(ConstructAckPacket(3, 3, 1)); Initialize(); - UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0); + ChunkedUploadDataStream upload_data_stream(0); request_.method = "POST"; request_.url = GURL("http://www.google.com/"); request_.upload_data_stream = &upload_data_stream; - ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback())); + ASSERT_EQ(OK, request_.upload_data_stream->Init( + TestCompletionCallback().callback())); ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_, callback_.callback())); ASSERT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_, callback_.callback())); - upload_data_stream.AppendChunk(nullptr, 0, true); + upload_data_stream.AppendData(nullptr, 0, true); ProcessPacket(ConstructAckPacket(1, 0, 0)); diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index 2f03f40..f1c1de2 100644 --- a/net/spdy/spdy_http_stream_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc @@ -14,10 +14,10 @@ #include "crypto/ec_signature_creator.h" #include "crypto/signature_creator.h" #include "net/base/capturing_net_log.h" +#include "net/base/chunked_upload_data_stream.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" -#include "net/base/upload_data_stream.h" -#include "net/base/upload_element_reader.h" +#include "net/base/test_completion_callback.h" #include "net/cert/asn1_util.h" #include "net/http/http_request_info.h" #include "net/http/http_response_headers.h" @@ -338,10 +338,10 @@ TEST_P(SpdyHttpStreamTest, SendChunkedPost) { key); EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion()); - UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); + ChunkedUploadDataStream upload_stream(0); const int kFirstChunkSize = kUploadDataSize/2; - upload_stream.AppendChunk(kUploadData, kFirstChunkSize, false); - upload_stream.AppendChunk(kUploadData + kFirstChunkSize, + upload_stream.AppendData(kUploadData, kFirstChunkSize, false); + upload_stream.AppendData(kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true); HttpRequestInfo request; @@ -349,7 +349,7 @@ TEST_P(SpdyHttpStreamTest, SendChunkedPost) { request.url = GURL("http://www.google.com/"); request.upload_data_stream = &upload_stream; - ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); + ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); TestCompletionCallback callback; HttpResponseInfo response; @@ -413,15 +413,15 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPost) { writes, arraysize(writes), key); - UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); + ChunkedUploadDataStream upload_stream(0); HttpRequestInfo request; request.method = "POST"; request.url = GURL("http://www.google.com/"); request.upload_data_stream = &upload_stream; - ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); - upload_stream.AppendChunk(kUploadData, kUploadDataSize, false); + ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); + upload_stream.AppendData(kUploadData, kUploadDataSize, false); BoundNetLog net_log; scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true)); @@ -443,8 +443,8 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPost) { EXPECT_EQ(OK, callback.WaitForResult()); // Now append the final two chunks which will enqueue two more writes. - upload_stream.AppendChunk(kUploadData1, kUploadData1Size, false); - upload_stream.AppendChunk(kUploadData, kUploadDataSize, true); + upload_stream.AppendData(kUploadData1, kUploadData1Size, false); + upload_stream.AppendData(kUploadData, kUploadDataSize, true); // Finish writing all the chunks. deterministic_data()->RunFor(2); @@ -512,15 +512,15 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithEmptyFinalDataFrame) { writes, arraysize(writes), key); - UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); + ChunkedUploadDataStream upload_stream(0); HttpRequestInfo request; request.method = "POST"; request.url = GURL("http://www.google.com/"); request.upload_data_stream = &upload_stream; - ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); - upload_stream.AppendChunk(kUploadData, kUploadDataSize, false); + ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); + upload_stream.AppendData(kUploadData, kUploadDataSize, false); BoundNetLog net_log; scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true)); @@ -542,7 +542,7 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithEmptyFinalDataFrame) { EXPECT_EQ(OK, callback.WaitForResult()); // Now end the stream with an empty data frame and the FIN set. - upload_stream.AppendChunk(NULL, 0, true); + upload_stream.AppendData(NULL, 0, true); // Finish writing the final frame. deterministic_data()->RunFor(1); @@ -597,15 +597,15 @@ TEST_P(SpdyHttpStreamTest, ChunkedPostWithEmptyPayload) { writes, arraysize(writes), key); - UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); + ChunkedUploadDataStream upload_stream(0); HttpRequestInfo request; request.method = "POST"; request.url = GURL("http://www.google.com/"); request.upload_data_stream = &upload_stream; - ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); - upload_stream.AppendChunk("", 0, true); + ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); + upload_stream.AppendData("", 0, true); BoundNetLog net_log; scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true)); @@ -727,15 +727,15 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) { writes, arraysize(writes), key); - UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); + ChunkedUploadDataStream upload_stream(0); HttpRequestInfo request; request.method = "POST"; request.url = GURL("http://www.google.com/"); request.upload_data_stream = &upload_stream; - ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); - upload_stream.AppendChunk(kUploadData, kUploadDataSize, true); + ASSERT_EQ(OK, upload_stream.Init(TestCompletionCallback().callback())); + upload_stream.AppendData(kUploadData, kUploadDataSize, true); BoundNetLog net_log; scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true)); diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index 59a2f1b..92188ac 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc @@ -15,10 +15,11 @@ #include "base/strings/string_piece.h" #include "base/test/test_file_util.h" #include "net/base/auth.h" +#include "net/base/chunked_upload_data_stream.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/net_log_unittest.h" #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" #include "net/http/http_network_session_peer.h" #include "net/http/http_network_transaction.h" @@ -120,7 +121,7 @@ class SpdyNetworkTransactionTest } virtual ~SpdyNetworkTransactionTest() { - // UploadDataStream posts deletion tasks back to the message loop on + // UploadDataStream may post a deletion tasks back to the message loop on // destruction. upload_data_stream_.reset(); base::RunLoop().RunUntilIdle(); @@ -456,7 +457,7 @@ class SpdyNetworkTransactionTest element_readers.push_back( new UploadBytesElementReader(kUploadData, kUploadDataSize)); upload_data_stream_.reset( - new UploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(element_readers.Pass(), 0)); google_post_request_.method = "POST"; google_post_request_.url = GURL(kDefaultURL); @@ -481,7 +482,7 @@ class SpdyNetworkTransactionTest kUploadDataSize, base::Time())); upload_data_stream_.reset( - new UploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(element_readers.Pass(), 0)); google_post_request_.method = "POST"; google_post_request_.url = GURL(kDefaultURL); @@ -509,7 +510,7 @@ class SpdyNetworkTransactionTest kUploadDataSize, base::Time())); upload_data_stream_.reset( - new UploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(element_readers.Pass(), 0)); google_post_request_.method = "POST"; google_post_request_.url = GURL(kDefaultURL); @@ -542,7 +543,7 @@ class SpdyNetworkTransactionTest kUploadData + kFileRangeOffset + kFileRangeLength, kUploadDataSize - (kFileRangeOffset + kFileRangeLength))); upload_data_stream_.reset( - new UploadDataStream(element_readers.Pass(), 0)); + new ElementsUploadDataStream(element_readers.Pass(), 0)); google_post_request_.method = "POST"; google_post_request_.url = GURL(kDefaultURL); @@ -554,12 +555,11 @@ class SpdyNetworkTransactionTest const HttpRequestInfo& CreateChunkedPostRequest() { if (!google_chunked_post_request_initialized_) { - upload_data_stream_.reset( - new UploadDataStream(UploadDataStream::CHUNKED, 0)); + upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0)); google_chunked_post_request_.method = "POST"; google_chunked_post_request_.url = GURL(kDefaultURL); google_chunked_post_request_.upload_data_stream = - upload_data_stream_.get(); + upload_chunked_data_stream_.get(); google_chunked_post_request_initialized_ = true; } return google_chunked_post_request_; @@ -688,9 +688,14 @@ class SpdyNetworkTransactionTest callback.WaitForResult(); } + ChunkedUploadDataStream* upload_chunked_data_stream() const { + return upload_chunked_data_stream_.get(); + } + SpdyTestUtil spdy_util_; private: + scoped_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_; scoped_ptr<UploadDataStream> upload_data_stream_; bool google_get_request_initialized_; bool google_post_request_initialized_; @@ -774,7 +779,7 @@ TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) { // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make // sure it's being done right. if (spdy_util_.spdy_version() < SPDY3) { - switch(p) { + switch (p) { case HIGHEST: EXPECT_EQ(0, spdy_prio); break; @@ -1858,9 +1863,8 @@ TEST_P(SpdyNetworkTransactionTest, ChunkedPost) { // These chunks get merged into a single frame when being sent. const int kFirstChunkSize = kUploadDataSize/2; - helper.request().upload_data_stream->AppendChunk( - kUploadData, kFirstChunkSize, false); - helper.request().upload_data_stream->AppendChunk( + upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false); + upload_chunked_data_stream()->AppendData( kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true); helper.RunToCompletion(&data); @@ -1898,19 +1902,16 @@ TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) { DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL); - helper.request().upload_data_stream->AppendChunk( - kUploadData, kUploadDataSize, false); + upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false); helper.RunPreTestSetup(); helper.AddData(&data); ASSERT_TRUE(helper.StartDefaultTest()); base::RunLoop().RunUntilIdle(); - helper.request().upload_data_stream->AppendChunk( - kUploadData, kUploadDataSize, false); + upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false); base::RunLoop().RunUntilIdle(); - helper.request().upload_data_stream->AppendChunk( - kUploadData, kUploadDataSize, true); + upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true); helper.FinishDefaultTest(); helper.VerifyDataConsumed(); @@ -1972,7 +1973,7 @@ TEST_P(SpdyNetworkTransactionTest, EmptyPost) { BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); // Create an empty UploadDataStream. ScopedVector<UploadElementReader> element_readers; - UploadDataStream stream(element_readers.Pass(), 0); + ElementsUploadDataStream stream(element_readers.Pass(), 0); // Setup the request HttpRequestInfo request; @@ -2046,8 +2047,7 @@ TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) { EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); // Finish sending the request body. - helper.request().upload_data_stream->AppendChunk( - kUploadData, kUploadDataSize, true); + upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true); data.RunFor(2); std::string response_body; @@ -4442,7 +4442,7 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { writes.push_back(CreateMockWrite(*initial_settings_frame)); if (GetParam().protocol >= kProtoSPDY31) { writes.push_back(CreateMockWrite(*initial_window_update)); - }; + } writes.push_back(CreateMockWrite(*settings_frame)); writes.push_back(CreateMockWrite(*req)); @@ -4608,7 +4608,7 @@ TEST_P(SpdyNetworkTransactionTest, ProxyConnect) { }; scoped_ptr<OrderedSocketData> data; - switch(GetParam().ssl_type) { + switch (GetParam().ssl_type) { case SPDYNOSSL: data.reset(new OrderedSocketData(reads_SPDYNOSSL, arraysize(reads_SPDYNOSSL), @@ -4768,7 +4768,7 @@ TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) { }; scoped_ptr<OrderedSocketData> data_proxy; - switch(GetParam().ssl_type) { + switch (GetParam().ssl_type) { case SPDYNPN: data_proxy.reset(new OrderedSocketData(reads_SPDYNPN, arraysize(reads_SPDYNPN), @@ -5888,7 +5888,7 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) { element_readers.push_back( new UploadBytesElementReader(content->c_str(), content->size())); } - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); // Setup the request HttpRequestInfo request; @@ -6053,7 +6053,7 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) { element_readers.push_back( new UploadBytesElementReader(content->c_str(), content->size())); } - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); // Setup the request HttpRequestInfo request; @@ -6169,7 +6169,7 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) { upload_data_string.append(kUploadData, kUploadDataSize); element_readers.push_back(new UploadBytesElementReader( upload_data_string.c_str(), upload_data_string.size())); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -6286,7 +6286,7 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) { upload_data_string.append(kUploadData, kUploadDataSize); element_readers.push_back(new UploadBytesElementReader( upload_data_string.c_str(), upload_data_string.size())); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; @@ -6413,7 +6413,7 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) { upload_data_string.append(kUploadData, kUploadDataSize); element_readers.push_back(new UploadBytesElementReader( upload_data_string.c_str(), upload_data_string.size())); - UploadDataStream upload_data_stream(element_readers.Pass(), 0); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); HttpRequestInfo request; request.method = "POST"; diff --git a/net/test/spawned_test_server/spawner_communicator.cc b/net/test/spawned_test_server/spawner_communicator.cc index 9aadb87..53484ea 100644 --- a/net/test/spawned_test_server/spawner_communicator.cc +++ b/net/test/spawned_test_server/spawner_communicator.cc @@ -12,10 +12,10 @@ #include "base/time/time.h" #include "base/values.h" #include "build/build_config.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/net_util.h" #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/http/http_response_headers.h" #include "net/url_request/url_request_test_util.h" #include "url/gurl.h" @@ -188,10 +188,10 @@ void SpawnerCommunicator::SendCommandAndWaitForResultOnIOThread( cur_request_->set_method("POST"); scoped_ptr<UploadElementReader> reader( UploadOwnedBytesElementReader::CreateWithString(post_data)); - cur_request_->set_upload(make_scoped_ptr( - UploadDataStream::CreateWithReader(reader.Pass(), 0))); - net::HttpRequestHeaders headers; - headers.SetHeader(net::HttpRequestHeaders::kContentType, + cur_request_->set_upload( + ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0)); + HttpRequestHeaders headers; + headers.SetHeader(HttpRequestHeaders::kContentType, "application/json"); cur_request_->SetExtraRequestHeaders(headers); } diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc index f3e10fd0..5ea3921 100644 --- a/net/url_request/url_fetcher_core.cc +++ b/net/url_request/url_fetcher_core.cc @@ -14,6 +14,7 @@ #include "base/stl_util.h" #include "base/thread_task_runner_handle.h" #include "base/tracked_objects.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" @@ -548,8 +549,8 @@ void URLFetcherCore::StartURLRequest() { if (!upload_content_.empty()) { scoped_ptr<UploadElementReader> reader(new UploadBytesElementReader( upload_content_.data(), upload_content_.size())); - request_->set_upload(make_scoped_ptr( - UploadDataStream::CreateWithReader(reader.Pass(), 0))); + request_->set_upload( + ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0)); } else if (!upload_file_path_.empty()) { scoped_ptr<UploadElementReader> reader( new UploadFileElementReader(upload_file_task_runner_.get(), @@ -557,8 +558,8 @@ void URLFetcherCore::StartURLRequest() { upload_range_offset_, upload_range_length_, base::Time())); - request_->set_upload(make_scoped_ptr( - UploadDataStream::CreateWithReader(reader.Pass(), 0))); + request_->set_upload( + ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0)); } current_upload_bytes_ = -1; diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 311bb20..7ae48e8 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc @@ -18,6 +18,7 @@ #include "base/synchronization/lock.h" #include "base/values.h" #include "net/base/auth.h" +#include "net/base/chunked_upload_data_stream.h" #include "net/base/host_port_pair.h" #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" @@ -223,8 +224,8 @@ URLRequest::~URLRequest() { void URLRequest::EnableChunkedUpload() { DCHECK(!upload_data_stream_ || upload_data_stream_->is_chunked()); if (!upload_data_stream_) { - upload_data_stream_.reset( - new UploadDataStream(UploadDataStream::CHUNKED, 0)); + upload_chunked_data_stream_ = new ChunkedUploadDataStream(0); + upload_data_stream_.reset(upload_chunked_data_stream_); } } @@ -234,7 +235,7 @@ void URLRequest::AppendChunkToUpload(const char* bytes, DCHECK(upload_data_stream_); DCHECK(upload_data_stream_->is_chunked()); DCHECK_GT(bytes_len, 0); - upload_data_stream_->AppendChunk(bytes, bytes_len, is_last_chunk); + upload_chunked_data_stream_->AppendData(bytes, bytes_len, is_last_chunk); } void URLRequest::set_upload(scoped_ptr<UploadDataStream> upload) { diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index d8df8fe..a0d5789 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h @@ -48,6 +48,7 @@ class AppCacheInterceptor; namespace net { +class ChunkedUploadDataStream; class CookieOptions; class HostPortPair; class IOBuffer; @@ -791,6 +792,10 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe), scoped_refptr<URLRequestJob> job_; scoped_ptr<UploadDataStream> upload_data_stream_; + // TODO(mmenke): Make whether or not an upload is chunked transparent to the + // URLRequest. + ChunkedUploadDataStream* upload_chunked_data_stream_; + std::vector<GURL> url_chain_; GURL first_party_for_cookies_; GURL delegate_redirect_url_; diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 325a65a..e269f01 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc @@ -31,6 +31,8 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "net/base/capturing_net_log.h" +#include "net/base/chunked_upload_data_stream.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" @@ -242,10 +244,10 @@ bool ContainsString(const std::string& haystack, const char* needle) { return it != haystack.end(); } -UploadDataStream* CreateSimpleUploadData(const char* data) { +scoped_ptr<UploadDataStream> CreateSimpleUploadData(const char* data) { scoped_ptr<UploadElementReader> reader( new UploadBytesElementReader(data, strlen(data))); - return UploadDataStream::CreateWithReader(reader.Pass(), 0); + return ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0); } // Verify that the SSLInfo of a successful SSL connection has valid values. @@ -2556,7 +2558,7 @@ class URLRequestTestHTTP : public URLRequestTest { redirect_url, DEFAULT_PRIORITY, &d, NULL)); req->set_method(request_method); if (include_data) { - req->set_upload(make_scoped_ptr(CreateSimpleUploadData(kData))); + req->set_upload(CreateSimpleUploadData(kData)); HttpRequestHeaders headers; headers.SetHeader(HttpRequestHeaders::kContentLength, base::UintToString(arraysize(kData) - 1)); @@ -2602,7 +2604,7 @@ class URLRequestTestHTTP : public URLRequestTest { test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d, NULL)); r->set_method(method.c_str()); - r->set_upload(make_scoped_ptr(CreateSimpleUploadData(uploadBytes))); + r->set_upload(CreateSimpleUploadData(uploadBytes)); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -3015,7 +3017,7 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestPost) { scoped_ptr<URLRequest> r(context.CreateRequest( original_url, DEFAULT_PRIORITY, &d, NULL)); r->set_method("POST"); - r->set_upload(make_scoped_ptr(CreateSimpleUploadData(kData))); + r->set_upload(CreateSimpleUploadData(kData)); HttpRequestHeaders headers; headers.SetHeader(HttpRequestHeaders::kContentLength, base::UintToString(arraysize(kData) - 1)); @@ -4828,8 +4830,8 @@ TEST_F(URLRequestTestHTTP, PostFileTest) { 0, kuint64max, base::Time())); - r->set_upload(make_scoped_ptr( - new UploadDataStream(element_readers.Pass(), 0))); + r->set_upload(make_scoped_ptr<UploadDataStream>( + new ElementsUploadDataStream(element_readers.Pass(), 0))); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -4871,8 +4873,8 @@ TEST_F(URLRequestTestHTTP, PostUnreadableFileTest) { 0, kuint64max, base::Time())); - r->set_upload(make_scoped_ptr( - new UploadDataStream(element_readers.Pass(), 0))); + r->set_upload(make_scoped_ptr<UploadDataStream>( + new ElementsUploadDataStream(element_readers.Pass(), 0))); r->Start(); EXPECT_TRUE(r->is_pending()); @@ -5949,7 +5951,7 @@ TEST_F(URLRequestTestHTTP, Post302RedirectGet) { test_server_.GetURL("files/redirect-to-echoall"), DEFAULT_PRIORITY, &d, NULL)); req->set_method("POST"); - req->set_upload(make_scoped_ptr(CreateSimpleUploadData(kData))); + req->set_upload(CreateSimpleUploadData(kData)); // Set headers (some of which are specific to the POST). HttpRequestHeaders headers; @@ -6136,7 +6138,7 @@ TEST_F(URLRequestTestHTTP, InterceptPost302RedirectGet) { scoped_ptr<URLRequest> req(default_context_.CreateRequest( test_server_.GetURL("empty.html"), DEFAULT_PRIORITY, &d, NULL)); req->set_method("POST"); - req->set_upload(make_scoped_ptr(CreateSimpleUploadData(kData))); + req->set_upload(CreateSimpleUploadData(kData)); HttpRequestHeaders headers; headers.SetHeader(HttpRequestHeaders::kContentLength, base::UintToString(arraysize(kData) - 1)); @@ -6161,7 +6163,7 @@ TEST_F(URLRequestTestHTTP, InterceptPost307RedirectPost) { scoped_ptr<URLRequest> req(default_context_.CreateRequest( test_server_.GetURL("empty.html"), DEFAULT_PRIORITY, &d, NULL)); req->set_method("POST"); - req->set_upload(make_scoped_ptr(CreateSimpleUploadData(kData))); + req->set_upload(CreateSimpleUploadData(kData)); HttpRequestHeaders headers; headers.SetHeader(HttpRequestHeaders::kContentLength, base::UintToString(arraysize(kData) - 1)); @@ -6720,7 +6722,7 @@ TEST_F(HTTPSRequestTest, HSTSPreservesPosts) { test_server.host_port_pair().port())), DEFAULT_PRIORITY, &d, NULL)); req->set_method("POST"); - req->set_upload(make_scoped_ptr(CreateSimpleUploadData(kData))); + req->set_upload(CreateSimpleUploadData(kData)); req->Start(); base::RunLoop().Run(); diff --git a/remoting/host/token_validator_factory_impl.cc b/remoting/host/token_validator_factory_impl.cc index 1d2d011..c5fd3c3 100644 --- a/remoting/host/token_validator_factory_impl.cc +++ b/remoting/host/token_validator_factory_impl.cc @@ -13,11 +13,11 @@ #include "base/strings/string_util.h" #include "base/values.h" #include "crypto/random.h" +#include "net/base/elements_upload_data_stream.h" #include "net/base/escape.h" #include "net/base/io_buffer.h" #include "net/base/request_priority.h" #include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_status.h" @@ -90,8 +90,8 @@ void TokenValidatorImpl::StartValidateRequest(const std::string& token) { scoped_ptr<net::UploadElementReader> reader( new net::UploadBytesElementReader( post_body_.data(), post_body_.size())); - request_->set_upload(make_scoped_ptr( - net::UploadDataStream::CreateWithReader(reader.Pass(), 0))); + request_->set_upload( + net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0)); request_->Start(); } |