diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-21 07:51:31 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-21 07:51:31 +0000 |
commit | 2c03980fa0873647293a0e8fade9b6d0adc1193c (patch) | |
tree | 0edbea1a354e6457af64991a5ee1d77cfab17349 /webkit | |
parent | f7528eca39a09fab8d37f5435e2eb0ef7139776d (diff) | |
download | chromium_src-2c03980fa0873647293a0e8fade9b6d0adc1193c.zip chromium_src-2c03980fa0873647293a0e8fade9b6d0adc1193c.tar.gz chromium_src-2c03980fa0873647293a0e8fade9b6d0adc1193c.tar.bz2 |
Split net::UploadData into two: for resource request IPC and for upload handling
Introducing webkit_glue::ResourceRequestBody as a content-level abstraction corresponding to WebHTTPBody and as an alternative of net::UploadData in ResourceRequest.
This interface can contain content-level objects like Blob (or FileSystem URL in later patches) while net::UploadData should NOT.
This patch also removes Blob support in net::UploadData.
BUG=110119
TEST=existing tests
Review URL: https://chromiumcodereview.appspot.com/10834289
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152528 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/blob/blob_storage_controller.cc | 29 | ||||
-rw-r--r-- | webkit/blob/blob_storage_controller.h | 13 | ||||
-rw-r--r-- | webkit/blob/blob_storage_controller_unittest.cc | 163 | ||||
-rw-r--r-- | webkit/glue/resource_loader_bridge.h | 30 | ||||
-rw-r--r-- | webkit/glue/resource_request_body.cc | 76 | ||||
-rw-r--r-- | webkit/glue/resource_request_body.h | 181 | ||||
-rw-r--r-- | webkit/glue/resource_request_body_unittest.cc | 48 | ||||
-rw-r--r-- | webkit/glue/webkit_glue.gypi | 2 | ||||
-rw-r--r-- | webkit/glue/weburlloader_impl.cc | 16 | ||||
-rw-r--r-- | webkit/tools/test_shell/simple_resource_loader_bridge.cc | 46 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell.gypi | 1 |
11 files changed, 440 insertions, 165 deletions
diff --git a/webkit/blob/blob_storage_controller.cc b/webkit/blob/blob_storage_controller.cc index 6a10811..4c3c3bb 100644 --- a/webkit/blob/blob_storage_controller.cc +++ b/webkit/blob/blob_storage_controller.cc @@ -6,8 +6,10 @@ #include "base/logging.h" #include "googleurl/src/gurl.h" -#include "net/base/upload_data.h" #include "webkit/blob/blob_data.h" +#include "webkit/glue/resource_request_body.h" + +using webkit_glue::ResourceRequestBody; namespace webkit_blob { @@ -169,15 +171,15 @@ BlobData* BlobStorageController::GetBlobDataFromUrl(const GURL& url) { return (found != blob_map_.end()) ? found->second : NULL; } -void BlobStorageController::ResolveBlobReferencesInUploadData( - net::UploadData* upload_data) { - DCHECK(upload_data); +void BlobStorageController::ResolveBlobReferencesInRequestBody( + ResourceRequestBody* request_body) { + DCHECK(request_body); - std::vector<net::UploadElement>* uploads = - upload_data->elements_mutable(); - std::vector<net::UploadElement>::iterator iter; + std::vector<ResourceRequestBody::Element>* uploads = + request_body->elements_mutable(); + std::vector<ResourceRequestBody::Element>::iterator iter; for (iter = uploads->begin(); iter != uploads->end();) { - if (iter->type() != net::UploadElement::TYPE_BLOB) { + if (iter->type() != ResourceRequestBody::TYPE_BLOB) { iter++; continue; } @@ -202,22 +204,19 @@ void BlobStorageController::ResolveBlobReferencesInUploadData( // Ensure the blob and any attached shareable files survive until // upload completion. - upload_data->SetUserData(blob_data, - new base::UserDataAdapter<BlobData>(blob_data)); + request_body->SetUserData( + blob_data, new base::UserDataAdapter<BlobData>(blob_data)); // Insert the elements in the referred blob data. // Note that we traverse from the bottom so that the elements can be // inserted in the original order. for (size_t i = blob_data->items().size(); i > 0; --i) { - iter = uploads->insert(iter, net::UploadElement()); + iter = uploads->insert(iter, ResourceRequestBody::Element()); const BlobData::Item& item = blob_data->items().at(i - 1); switch (item.type) { case BlobData::TYPE_DATA: - // TODO(jianli): Figure out how to avoid copying the data. - // TODO(michaeln): Now that blob_data surives for the duration, - // maybe UploadData could take a raw ptr without having to copy. - iter->SetToBytes( + iter->SetToSharedBytes( &item.data.at(0) + static_cast<int>(item.offset), static_cast<int>(item.length)); break; diff --git a/webkit/blob/blob_storage_controller.h b/webkit/blob/blob_storage_controller.h index a32fab3..fddd6ff 100644 --- a/webkit/blob/blob_storage_controller.h +++ b/webkit/blob/blob_storage_controller.h @@ -13,6 +13,7 @@ #include "base/process.h" #include "webkit/blob/blob_data.h" #include "webkit/blob/blob_export.h" +#include "webkit/glue/resource_request_body.h" class GURL; class FilePath; @@ -20,8 +21,9 @@ class FilePath; namespace base { class Time; } -namespace net { -class UploadData; + +namespace webkit_glue { +class ResourceRequestBody; } namespace webkit_blob { @@ -40,9 +42,10 @@ class BLOB_EXPORT BlobStorageController { void RemoveBlob(const GURL& url); BlobData* GetBlobDataFromUrl(const GURL& url); - // If there is any blob reference in the upload data, it will get resolved - // and updated in place. - void ResolveBlobReferencesInUploadData(net::UploadData* upload_data); + // If there is any blob reference in the resource request body, it will get + // resolved and updated in place. + void ResolveBlobReferencesInRequestBody( + webkit_glue::ResourceRequestBody* request_body); private: friend class ViewBlobInternalsJob; diff --git a/webkit/blob/blob_storage_controller_unittest.cc b/webkit/blob/blob_storage_controller_unittest.cc index ff98e22..48699a4 100644 --- a/webkit/blob/blob_storage_controller_unittest.cc +++ b/webkit/blob/blob_storage_controller_unittest.cc @@ -6,12 +6,12 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/time.h" -#include "net/base/upload_data.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/blob/blob_data.h" #include "webkit/blob/blob_storage_controller.h" +#include "webkit/glue/resource_request_body.h" -using net::UploadData; +using webkit_glue::ResourceRequestBody; namespace webkit_blob { @@ -76,7 +76,7 @@ TEST(BlobStorageControllerTest, RegisterBlobUrl) { EXPECT_TRUE(!blob_data_found); } -TEST(BlobStorageControllerTest, ResolveBlobReferencesInUploadData) { +TEST(BlobStorageControllerTest, ResolveBlobReferencesInRequestBody) { // Setup blob data for testing. base::Time time1, time2; base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); @@ -102,7 +102,7 @@ TEST(BlobStorageControllerTest, ResolveBlobReferencesInUploadData) { blob_storage_controller.CloneBlob(blob_url3, blob_url2); // Setup upload data elements for comparison. - net::UploadElement blob_element1, blob_element2; + ResourceRequestBody::Element blob_element1, blob_element2; blob_element1.SetToBytes( blob_data->items().at(0).data.c_str() + static_cast<int>(blob_data->items().at(0).offset), @@ -113,124 +113,131 @@ TEST(BlobStorageControllerTest, ResolveBlobReferencesInUploadData) { blob_data->items().at(1).length, blob_data->items().at(1).expected_modification_time); - net::UploadElement upload_element1, upload_element2; + ResourceRequestBody::Element upload_element1, upload_element2; upload_element1.SetToBytes("Hello", 5); upload_element2.SetToFilePathRange( FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2); // Test no blob reference. - scoped_refptr<UploadData> upload_data(new UploadData()); - upload_data->AppendBytes( - &upload_element1.bytes().at(0), - upload_element1.bytes().size()); - upload_data->AppendFileRange( + scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody()); + request_body->AppendBytes( + upload_element1.bytes(), + upload_element1.bytes_length()); + request_body->AppendFileRange( upload_element2.file_path(), upload_element2.file_range_offset(), upload_element2.file_range_length(), upload_element2.expected_file_modification_time()); - blob_storage_controller.ResolveBlobReferencesInUploadData(upload_data.get()); - ASSERT_EQ(upload_data->elements()->size(), 2U); - EXPECT_TRUE(upload_data->elements()->at(0) == upload_element1); - EXPECT_TRUE(upload_data->elements()->at(1) == upload_element2); + blob_storage_controller.ResolveBlobReferencesInRequestBody( + request_body.get()); + ASSERT_EQ(request_body->elements()->size(), 2U); + EXPECT_TRUE(request_body->elements()->at(0) == upload_element1); + EXPECT_TRUE(request_body->elements()->at(1) == upload_element2); // Test having only one blob reference that refers to empty blob data. - upload_data = new UploadData(); - upload_data->AppendBlob(blob_url0); + request_body = new ResourceRequestBody(); + request_body->AppendBlob(blob_url0); - blob_storage_controller.ResolveBlobReferencesInUploadData(upload_data.get()); - ASSERT_EQ(upload_data->elements()->size(), 0U); + blob_storage_controller.ResolveBlobReferencesInRequestBody( + request_body.get()); + ASSERT_EQ(request_body->elements()->size(), 0U); // Test having only one blob reference. - upload_data = new UploadData(); - upload_data->AppendBlob(blob_url1); + request_body = new ResourceRequestBody(); + request_body->AppendBlob(blob_url1); - blob_storage_controller.ResolveBlobReferencesInUploadData(upload_data.get()); - ASSERT_EQ(upload_data->elements()->size(), 2U); - EXPECT_TRUE(upload_data->elements()->at(0) == blob_element1); - EXPECT_TRUE(upload_data->elements()->at(1) == blob_element2); + blob_storage_controller.ResolveBlobReferencesInRequestBody( + request_body.get()); + ASSERT_EQ(request_body->elements()->size(), 2U); + EXPECT_TRUE(request_body->elements()->at(0) == blob_element1); + EXPECT_TRUE(request_body->elements()->at(1) == blob_element2); // Test having one blob reference at the beginning. - upload_data = new UploadData(); - upload_data->AppendBlob(blob_url1); - upload_data->AppendBytes( - &upload_element1.bytes().at(0), - upload_element1.bytes().size()); - upload_data->AppendFileRange( + request_body = new ResourceRequestBody(); + request_body->AppendBlob(blob_url1); + request_body->AppendBytes( + upload_element1.bytes(), + upload_element1.bytes_length()); + request_body->AppendFileRange( upload_element2.file_path(), upload_element2.file_range_offset(), upload_element2.file_range_length(), upload_element2.expected_file_modification_time()); - blob_storage_controller.ResolveBlobReferencesInUploadData(upload_data.get()); - ASSERT_EQ(upload_data->elements()->size(), 4U); - EXPECT_TRUE(upload_data->elements()->at(0) == blob_element1); - EXPECT_TRUE(upload_data->elements()->at(1) == blob_element2); - EXPECT_TRUE(upload_data->elements()->at(2) == upload_element1); - EXPECT_TRUE(upload_data->elements()->at(3) == upload_element2); + blob_storage_controller.ResolveBlobReferencesInRequestBody( + request_body.get()); + ASSERT_EQ(request_body->elements()->size(), 4U); + EXPECT_TRUE(request_body->elements()->at(0) == blob_element1); + EXPECT_TRUE(request_body->elements()->at(1) == blob_element2); + EXPECT_TRUE(request_body->elements()->at(2) == upload_element1); + EXPECT_TRUE(request_body->elements()->at(3) == upload_element2); // Test having one blob reference at the end. - upload_data = new UploadData(); - upload_data->AppendBytes( - &upload_element1.bytes().at(0), - upload_element1.bytes().size()); - upload_data->AppendFileRange( + request_body = new ResourceRequestBody(); + request_body->AppendBytes( + upload_element1.bytes(), + upload_element1.bytes_length()); + request_body->AppendFileRange( upload_element2.file_path(), upload_element2.file_range_offset(), upload_element2.file_range_length(), upload_element2.expected_file_modification_time()); - upload_data->AppendBlob(blob_url1); + request_body->AppendBlob(blob_url1); - blob_storage_controller.ResolveBlobReferencesInUploadData(upload_data.get()); - ASSERT_EQ(upload_data->elements()->size(), 4U); - EXPECT_TRUE(upload_data->elements()->at(0) == upload_element1); - EXPECT_TRUE(upload_data->elements()->at(1) == upload_element2); - EXPECT_TRUE(upload_data->elements()->at(2) == blob_element1); - EXPECT_TRUE(upload_data->elements()->at(3) == blob_element2); + blob_storage_controller.ResolveBlobReferencesInRequestBody( + request_body.get()); + ASSERT_EQ(request_body->elements()->size(), 4U); + EXPECT_TRUE(request_body->elements()->at(0) == upload_element1); + EXPECT_TRUE(request_body->elements()->at(1) == upload_element2); + EXPECT_TRUE(request_body->elements()->at(2) == blob_element1); + EXPECT_TRUE(request_body->elements()->at(3) == blob_element2); // Test having one blob reference in the middle. - upload_data = new UploadData(); - upload_data->AppendBytes( - &upload_element1.bytes().at(0), - upload_element1.bytes().size()); - upload_data->AppendBlob(blob_url1); - upload_data->AppendFileRange( + request_body = new ResourceRequestBody(); + request_body->AppendBytes( + upload_element1.bytes(), + upload_element1.bytes_length()); + request_body->AppendBlob(blob_url1); + request_body->AppendFileRange( upload_element2.file_path(), upload_element2.file_range_offset(), upload_element2.file_range_length(), upload_element2.expected_file_modification_time()); - blob_storage_controller.ResolveBlobReferencesInUploadData(upload_data.get()); - ASSERT_EQ(upload_data->elements()->size(), 4U); - EXPECT_TRUE(upload_data->elements()->at(0) == upload_element1); - EXPECT_TRUE(upload_data->elements()->at(1) == blob_element1); - EXPECT_TRUE(upload_data->elements()->at(2) == blob_element2); - EXPECT_TRUE(upload_data->elements()->at(3) == upload_element2); + blob_storage_controller.ResolveBlobReferencesInRequestBody( + request_body.get()); + ASSERT_EQ(request_body->elements()->size(), 4U); + EXPECT_TRUE(request_body->elements()->at(0) == upload_element1); + EXPECT_TRUE(request_body->elements()->at(1) == blob_element1); + EXPECT_TRUE(request_body->elements()->at(2) == blob_element2); + EXPECT_TRUE(request_body->elements()->at(3) == upload_element2); // Test having multiple blob references. - upload_data = new UploadData(); - upload_data->AppendBlob(blob_url1); - upload_data->AppendBytes( - &upload_element1.bytes().at(0), - upload_element1.bytes().size()); - upload_data->AppendBlob(blob_url2); - upload_data->AppendBlob(blob_url3); - upload_data->AppendFileRange( + request_body = new ResourceRequestBody(); + request_body->AppendBlob(blob_url1); + request_body->AppendBytes( + upload_element1.bytes(), + upload_element1.bytes_length()); + request_body->AppendBlob(blob_url2); + request_body->AppendBlob(blob_url3); + request_body->AppendFileRange( upload_element2.file_path(), upload_element2.file_range_offset(), upload_element2.file_range_length(), upload_element2.expected_file_modification_time()); - blob_storage_controller.ResolveBlobReferencesInUploadData(upload_data.get()); - ASSERT_EQ(upload_data->elements()->size(), 8U); - EXPECT_TRUE(upload_data->elements()->at(0) == blob_element1); - EXPECT_TRUE(upload_data->elements()->at(1) == blob_element2); - EXPECT_TRUE(upload_data->elements()->at(2) == upload_element1); - EXPECT_TRUE(upload_data->elements()->at(3) == blob_element1); - EXPECT_TRUE(upload_data->elements()->at(4) == blob_element2); - EXPECT_TRUE(upload_data->elements()->at(5) == blob_element1); - EXPECT_TRUE(upload_data->elements()->at(6) == blob_element2); - EXPECT_TRUE(upload_data->elements()->at(7) == upload_element2); + blob_storage_controller.ResolveBlobReferencesInRequestBody( + request_body.get()); + ASSERT_EQ(request_body->elements()->size(), 8U); + EXPECT_TRUE(request_body->elements()->at(0) == blob_element1); + EXPECT_TRUE(request_body->elements()->at(1) == blob_element2); + EXPECT_TRUE(request_body->elements()->at(2) == upload_element1); + EXPECT_TRUE(request_body->elements()->at(3) == blob_element1); + EXPECT_TRUE(request_body->elements()->at(4) == blob_element2); + EXPECT_TRUE(request_body->elements()->at(5) == blob_element1); + EXPECT_TRUE(request_body->elements()->at(6) == blob_element2); + EXPECT_TRUE(request_body->elements()->at(7) == upload_element2); } } // namespace webkit_blob diff --git a/webkit/glue/resource_loader_bridge.h b/webkit/glue/resource_loader_bridge.h index 70db933..e699574 100644 --- a/webkit/glue/resource_loader_bridge.h +++ b/webkit/glue/resource_loader_bridge.h @@ -41,6 +41,7 @@ class HttpResponseHeaders; } namespace webkit_glue { +class ResourceRequestBody; // Structure containing timing information for the request. It addresses // http://groups.google.com/group/http-archive-specification/web/har-1-1-spec @@ -348,32 +349,9 @@ class ResourceLoaderBridge { // anybody can delete at any time, INCLUDING during processing of callbacks. WEBKIT_GLUE_EXPORT virtual ~ResourceLoaderBridge(); - // Call this method before calling Start() to append a chunk of binary data - // to the request body. May only be used with HTTP(S) POST requests. - virtual void AppendDataToUpload(const char* data, int data_len) = 0; - - // Call this method before calling Start() to append the contents of a file - // to the request body. May only be used with HTTP(S) POST requests. - void AppendFileToUpload(const FilePath& file_path) { - AppendFileRangeToUpload(file_path, 0, kuint64max, base::Time()); - } - - // Call this method before calling Start() to append the contents of a file - // to the request body. May only be used with HTTP(S) POST requests. - virtual void AppendFileRangeToUpload( - const FilePath& file_path, - uint64 offset, - uint64 length, - const base::Time& expected_modification_time) = 0; - - // Call this method before calling Start() to append the contents of a blob - // to the request body. May only be used with HTTP(S) POST requests. - virtual void AppendBlobToUpload(const GURL& blob_url) = 0; - - // Call this method before calling Start() to assign an upload identifier to - // this request. This is used to enable caching of POST responses. A value - // of 0 implies the unspecified identifier. - virtual void SetUploadIdentifier(int64 identifier) = 0; + // Call this method before calling Start() to set the request body. + // May only be used with HTTP(S) POST requests. + virtual void SetRequestBody(ResourceRequestBody* request_body) = 0; // Call this method to initiate the request. If this method succeeds, then // the peer's methods will be called asynchronously to report various events. diff --git a/webkit/glue/resource_request_body.cc b/webkit/glue/resource_request_body.cc new file mode 100644 index 0000000..1cd10e8 --- /dev/null +++ b/webkit/glue/resource_request_body.cc @@ -0,0 +1,76 @@ +// 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 "webkit/glue/resource_request_body.h" + +#include "base/logging.h" +#include "net/base/upload_data.h" + +namespace webkit_glue { + +ResourceRequestBody::Element::Element() + : type_(TYPE_BYTES), + bytes_start_(NULL), + bytes_length_(0), + file_range_offset_(0), + file_range_length_(kuint64max) { +} + +ResourceRequestBody::Element::~Element() {} + +ResourceRequestBody::ResourceRequestBody() : identifier_(0) {} + +void ResourceRequestBody::AppendBytes(const char* bytes, int bytes_len) { + if (bytes_len > 0) { + elements_.push_back(Element()); + elements_.back().SetToBytes(bytes, bytes_len); + } +} + +void ResourceRequestBody::AppendFileRange( + const FilePath& file_path, + uint64 offset, uint64 length, + const base::Time& expected_modification_time) { + elements_.push_back(Element()); + elements_.back().SetToFilePathRange(file_path, offset, length, + expected_modification_time); +} + +void ResourceRequestBody::AppendBlob(const GURL& blob_url) { + elements_.push_back(Element()); + elements_.back().SetToBlobUrl(blob_url); +} + +net::UploadData* ResourceRequestBody::CreateUploadData() { + net::UploadData* upload_data = new net::UploadData; + // We attach 'this' to UploadData so that we do not need to copy + // bytes for TYPE_BYTES. + upload_data->SetUserData( + this, new base::UserDataAdapter<ResourceRequestBody>(this)); + std::vector<net::UploadElement>* uploads = + upload_data->elements_mutable(); + for (size_t i = 0; i < elements_.size(); ++i) { + const Element& element = elements_[i]; + if (element.type() == TYPE_BYTES) { + uploads->push_back(net::UploadElement()); + uploads->back().SetToSharedBytes(element.bytes(), + element.bytes_length()); + continue; + } + + DCHECK(element.type() == TYPE_FILE); + uploads->push_back(net::UploadElement()); + uploads->back().SetToFilePathRange( + element.file_path(), + element.file_range_offset(), + element.file_range_length(), + element.expected_file_modification_time()); + } + upload_data->set_identifier(identifier_); + return upload_data; +} + +ResourceRequestBody::~ResourceRequestBody() {} + +} // namespace webkit_glue diff --git a/webkit/glue/resource_request_body.h b/webkit/glue/resource_request_body.h new file mode 100644 index 0000000..0b3ef0d --- /dev/null +++ b/webkit/glue/resource_request_body.h @@ -0,0 +1,181 @@ +// 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 WEBKIT_GLUE_RESOURCE_REQUEST_BODY_H_ +#define WEBKIT_GLUE_RESOURCE_REQUEST_BODY_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/supports_user_data.h" +#include "base/time.h" +#include "googleurl/src/gurl.h" +#include "webkit/glue/webkit_glue_export.h" + +namespace net { +class UploadData; +} + +namespace webkit_glue { + +// A struct used to represent upload data. The data field is populated by +// WebURLLoader from the data given as WebHTTPBody. +// TODO(kinuko): This is basically a duplicate of net::UploadData but +// with support for higher-level abstraction data. We should reduce the +// code duplicate by sharing code for similar data structs: +// ResourceRequestBody::Element and BlobData::Item. +class WEBKIT_GLUE_EXPORT ResourceRequestBody + : public base::RefCounted<ResourceRequestBody>, + public base::SupportsUserData { + public: + enum Type { + TYPE_BYTES, + TYPE_FILE, + TYPE_BLOB, + }; + + class WEBKIT_GLUE_EXPORT Element { + public: + Element(); + ~Element(); + + Type type() const { return type_; } + // Explicitly sets the type of this Element. Used during IPC + // marshalling. + void set_type(Type type) { + type_ = type; + } + + const char* bytes() const { return bytes_start_ ? bytes_start_ : &buf_[0]; } + uint64 bytes_length() const { return buf_.size() + bytes_length_; } + const FilePath& file_path() const { return file_path_; } + uint64 file_range_offset() const { return file_range_offset_; } + uint64 file_range_length() const { return file_range_length_; } + // If NULL time is returned, we do not do the check. + const base::Time& expected_file_modification_time() const { + return expected_file_modification_time_; + } + const GURL& blob_url() const { return blob_url_; } + + void SetToBytes(const char* bytes, int bytes_len) { + type_ = TYPE_BYTES; + buf_.assign(bytes, bytes + bytes_len); + } + + // This does not copy the given data and the caller should make sure + // the data is secured somewhere else (e.g. by attaching the data + // using SetUserData). + void SetToSharedBytes(const char* bytes, int bytes_len) { + type_ = TYPE_BYTES; + bytes_start_ = bytes; + bytes_length_ = bytes_len; + } + + void SetToFilePath(const FilePath& path) { + SetToFilePathRange(path, 0, kuint64max, base::Time()); + } + + // If expected_modification_time is NULL, we do not check for the file + // change. Also note that the granularity for comparison is time_t, not + // the full precision. + void SetToFilePathRange(const FilePath& path, + uint64 offset, uint64 length, + const base::Time& expected_modification_time) { + type_ = TYPE_FILE; + file_path_ = path; + file_range_offset_ = offset; + file_range_length_ = length; + expected_file_modification_time_ = expected_modification_time; + } + + void SetToBlobUrl(const GURL& blob_url) { + type_ = TYPE_BLOB; + blob_url_ = blob_url; + } + + private: + Type type_; + std::vector<char> buf_; + const char* bytes_start_; + uint64 bytes_length_; + FilePath file_path_; + uint64 file_range_offset_; + uint64 file_range_length_; + base::Time expected_file_modification_time_; + GURL blob_url_; + }; + + ResourceRequestBody(); + + void AppendBytes(const char* bytes, int bytes_len); + void AppendFileRange(const FilePath& file_path, + uint64 offset, uint64 length, + const base::Time& expected_modification_time); + void AppendBlob(const GURL& blob_url); + + // Creates a new UploadData from this request body. + // At this stage the elements should not contain any TYPE_BLOB items + // (i.e. must have resolved them by ResolveBlobReferencesInUploadData). + // TODO(kinuko): Clean up this hack. + net::UploadData* CreateUploadData(); + + const std::vector<Element>* elements() const { + return &elements_; + } + + std::vector<Element>* elements_mutable() { + return &elements_; + } + + void swap_elements(std::vector<Element>* elements) { + elements_.swap(*elements); + } + + // 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. + void set_identifier(int64 id) { identifier_ = id; } + int64 identifier() const { return identifier_; } + + private: + friend class base::RefCounted<ResourceRequestBody>; + virtual ~ResourceRequestBody(); + + std::vector<Element> elements_; + int64 identifier_; + + DISALLOW_COPY_AND_ASSIGN(ResourceRequestBody); +}; + +#if defined(UNIT_TEST) +inline bool operator==(const ResourceRequestBody::Element& a, + const ResourceRequestBody::Element& b) { + if (a.type() != b.type()) + return false; + if (a.type() == ResourceRequestBody::TYPE_BYTES) + return a.bytes_length() == b.bytes_length() && + memcmp(a.bytes(), b.bytes(), b.bytes_length()) == 0; + if (a.type() == ResourceRequestBody::TYPE_FILE) { + return a.file_path() == b.file_path() && + a.file_range_offset() == b.file_range_offset() && + a.file_range_length() == b.file_range_length() && + a.expected_file_modification_time() == + b.expected_file_modification_time(); + } + if (a.type() == ResourceRequestBody::TYPE_BLOB) + return a.blob_url() == b.blob_url(); + return false; +} + +inline bool operator!=(const ResourceRequestBody::Element& a, + const ResourceRequestBody::Element& b) { + return !(a == b); +} +#endif // defined(UNIT_TEST) + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_RESOURCE_REQUEST_BODY_H_ diff --git a/webkit/glue/resource_request_body_unittest.cc b/webkit/glue/resource_request_body_unittest.cc new file mode 100644 index 0000000..897eb56 --- /dev/null +++ b/webkit/glue/resource_request_body_unittest.cc @@ -0,0 +1,48 @@ +// 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 "webkit/glue/resource_request_body.h" + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/time.h" +#include "googleurl/src/gurl.h" +#include "net/base/upload_data.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace webkit_glue { + +TEST(ResourceRequestBodyTest, CreateUploadDataTest) { + scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody; + + const char kData[] = "123"; + const FilePath::StringType kFilePath = FILE_PATH_LITERAL("abc"); + const uint64 kFileOffset = 10U; + const uint64 kFileLength = 100U; + const base::Time kFileTime = base::Time::FromDoubleT(999); + const int64 kIdentifier = 12345; + + request_body->AppendBytes(kData, arraysize(kData) - 1); + request_body->AppendFileRange(FilePath(kFilePath), + kFileOffset, kFileLength, kFileTime); + request_body->set_identifier(kIdentifier); + + scoped_refptr<net::UploadData> upload = request_body->CreateUploadData(); + + EXPECT_EQ(kIdentifier, upload->identifier()); + ASSERT_EQ(request_body->elements()->size(), upload->elements()->size()); + + const net::UploadElement& e1 = upload->elements()->at(0); + EXPECT_EQ(net::UploadElement::TYPE_BYTES, e1.type()); + EXPECT_EQ(kData, std::string(e1.bytes(), e1.bytes_length())); + + const net::UploadElement& e2 = upload->elements()->at(1); + EXPECT_EQ(net::UploadElement::TYPE_FILE, e2.type()); + EXPECT_EQ(kFilePath, e2.file_path().value()); + EXPECT_EQ(kFileOffset, e2.file_range_offset()); + EXPECT_EQ(kFileLength, e2.file_range_length()); + EXPECT_EQ(kFileTime, e2.expected_file_modification_time()); +} + +} // namespace webkit_glue diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index ab23ee8..fa06cbd 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -378,6 +378,8 @@ 'resource_fetcher.h', 'resource_loader_bridge.cc', 'resource_loader_bridge.h', + 'resource_request_body.cc', + 'resource_request_body.h', 'resource_type.cc', 'resource_type.h', 'scoped_clipboard_writer_glue.cc', diff --git a/webkit/glue/weburlloader_impl.cc b/webkit/glue/weburlloader_impl.cc index 104795d..edc15424 100644 --- a/webkit/glue/weburlloader_impl.cc +++ b/webkit/glue/weburlloader_impl.cc @@ -32,6 +32,7 @@ #include "webkit/glue/ftp_directory_listing_response_delegate.h" #include "webkit/glue/multipart_response_delegate.h" #include "webkit/glue/resource_loader_bridge.h" +#include "webkit/glue/resource_request_body.h" #include "webkit/glue/webkit_glue.h" #include "webkit/glue/webkitplatformsupport_impl.h" #include "webkit/glue/weburlrequest_extradata_impl.h" @@ -444,22 +445,24 @@ void WebURLLoaderImpl::Context::Start( const WebHTTPBody& httpBody = request.httpBody(); size_t i = 0; WebHTTPBody::Element element; + scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody; while (httpBody.elementAt(i++, element)) { switch (element.type) { case WebHTTPBody::Element::TypeData: if (!element.data.isEmpty()) { // WebKit sometimes gives up empty data to append. These aren't // necessary so we just optimize those out here. - bridge_->AppendDataToUpload( + request_body->AppendBytes( element.data.data(), static_cast<int>(element.data.size())); } break; case WebHTTPBody::Element::TypeFile: if (element.fileLength == -1) { - bridge_->AppendFileToUpload( - WebStringToFilePath(element.filePath)); + request_body->AppendFileRange( + WebStringToFilePath(element.filePath), + 0, kuint64max, base::Time()); } else { - bridge_->AppendFileRangeToUpload( + request_body->AppendFileRange( WebStringToFilePath(element.filePath), static_cast<uint64>(element.fileStart), static_cast<uint64>(element.fileLength), @@ -467,13 +470,14 @@ void WebURLLoaderImpl::Context::Start( } break; case WebHTTPBody::Element::TypeBlob: - bridge_->AppendBlobToUpload(GURL(element.blobURL)); + request_body->AppendBlob(GURL(element.blobURL)); break; default: NOTREACHED(); } } - bridge_->SetUploadIdentifier(request.httpBody().identifier()); + request_body->set_identifier(request.httpBody().identifier()); + bridge_->SetRequestBody(request_body); } if (sync_load_response) { diff --git a/webkit/tools/test_shell/simple_resource_loader_bridge.cc b/webkit/tools/test_shell/simple_resource_loader_bridge.cc index e8caad4..6af385a 100644 --- a/webkit/tools/test_shell/simple_resource_loader_bridge.cc +++ b/webkit/tools/test_shell/simple_resource_loader_bridge.cc @@ -68,6 +68,7 @@ #include "webkit/fileapi/file_system_dir_url_request_job.h" #include "webkit/fileapi/file_system_url_request_job.h" #include "webkit/glue/resource_loader_bridge.h" +#include "webkit/glue/resource_request_body.h" #include "webkit/glue/webkit_glue.h" #include "webkit/tools/test_shell/simple_appcache_system.h" #include "webkit/tools/test_shell/simple_file_system.h" @@ -81,6 +82,7 @@ #endif using webkit_glue::ResourceLoaderBridge; +using webkit_glue::ResourceRequestBody; using webkit_glue::ResourceResponseInfo; using net::StaticCookiePolicy; using net::HttpResponseHeaders; @@ -279,7 +281,7 @@ struct RequestParams { ResourceType::Type request_type; int appcache_host_id; bool download_to_file; - scoped_refptr<net::UploadData> upload; + scoped_refptr<ResourceRequestBody> request_body; }; // The interval for calls to RequestProxy::MaybeUpdateUploadProgress @@ -415,10 +417,10 @@ class RequestProxy void AsyncStart(RequestParams* params) { // Might need to resolve the blob references in the upload data. - if (params->upload) { + if (params->request_body) { static_cast<TestShellRequestContext*>(g_request_context)-> - blob_storage_controller()->ResolveBlobReferencesInUploadData( - params->upload.get()); + blob_storage_controller()->ResolveBlobReferencesInRequestBody( + params->request_body.get()); } request_.reset(new net::URLRequest(params->url, this, g_request_context)); @@ -431,7 +433,8 @@ class RequestProxy headers.AddHeadersFromString(params->headers); request_->SetExtraRequestHeaders(headers); request_->set_load_flags(params->load_flags); - request_->set_upload(params->upload.get()); + if (params->request_body) + request_->set_upload(params->request_body->CreateUploadData()); SimpleAppCacheSystem::SetExtraRequestInfo( request_.get(), params->appcache_host_id, params->request_type); @@ -874,37 +877,10 @@ class ResourceLoaderBridgeImpl : public ResourceLoaderBridge { // -------------------------------------------------------------------------- // ResourceLoaderBridge implementation: - virtual void AppendDataToUpload(const char* data, int data_len) { + virtual void SetRequestBody(ResourceRequestBody* request_body) { DCHECK(params_.get()); - if (!params_->upload) - params_->upload = new net::UploadData(); - params_->upload->AppendBytes(data, data_len); - } - - virtual void AppendFileRangeToUpload( - const FilePath& file_path, - uint64 offset, - uint64 length, - const base::Time& expected_modification_time) { - DCHECK(params_.get()); - if (!params_->upload) - params_->upload = new net::UploadData(); - params_->upload->AppendFileRange(file_path, offset, length, - expected_modification_time); - } - - virtual void AppendBlobToUpload(const GURL& blob_url) { - DCHECK(params_.get()); - if (!params_->upload) - params_->upload = new net::UploadData(); - params_->upload->AppendBlob(blob_url); - } - - virtual void SetUploadIdentifier(int64 identifier) { - DCHECK(params_.get()); - if (!params_->upload) - params_->upload = new net::UploadData(); - params_->upload->set_identifier(identifier); + DCHECK(!params_->request_body); + params_->request_body = request_body; } virtual bool Start(Peer* peer) { diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi index 7a832b2..378cfd30 100644 --- a/webkit/tools/test_shell/test_shell.gypi +++ b/webkit/tools/test_shell/test_shell.gypi @@ -372,6 +372,7 @@ '../../glue/multipart_response_delegate_unittest.cc', '../../glue/regular_expression_unittest.cc', '../../glue/resource_fetcher_unittest.cc', + '../../glue/resource_request_body_unittest.cc', '../../glue/unittest_test_server.h', '../../glue/webcursor_unittest.cc', '../../glue/webkit_glue_unittest.cc', |