diff options
author | tommycli@chromium.org <tommycli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-15 09:55:38 +0000 |
---|---|---|
committer | tommycli@chromium.org <tommycli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-15 09:55:38 +0000 |
commit | 89b429341068c7b6d4c1129052e7abfc708d6161 (patch) | |
tree | 208aa003365726a6ae615da869b9ab19dc451c09 | |
parent | 24e4cac9b53c6bebf0bafc40213ff67fa9caedb2 (diff) | |
download | chromium_src-89b429341068c7b6d4c1129052e7abfc708d6161.zip chromium_src-89b429341068c7b6d4c1129052e7abfc708d6161.tar.gz chromium_src-89b429341068c7b6d4c1129052e7abfc708d6161.tar.bz2 |
This is to allow extensions to determine the total length of Javascript blobs.
This cannot AFAIK be done via passing the length in a custom binding, as base::Value does not support int64 a.k.a. 'long long' types.
The total blob length is going to be used in media_galleries_api.cc to construct the SafeMediaMetadataParser in a followup CL. It appears unused in this patch.
BUG=
Review URL: https://codereview.chromium.org/129823003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244860 0039d316-1c4b-4281-b951-d872f2087c98
11 files changed, 94 insertions, 23 deletions
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service.cc b/chrome/browser/extensions/api/feedback_private/feedback_service.cc index b66831f..f32840cc 100644 --- a/chrome/browser/extensions/api/feedback_private/feedback_service.cc +++ b/chrome/browser/extensions/api/feedback_private/feedback_service.cc @@ -66,7 +66,8 @@ void FeedbackService::SendFeedback( CompleteSendFeedback(); } -void FeedbackService::AttachedFileCallback(scoped_ptr<std::string> data) { +void FeedbackService::AttachedFileCallback(scoped_ptr<std::string> data, + int64 /* total_blob_length */) { if (!data.get()) feedback_data_->set_attached_file_uuid(std::string()); else @@ -75,7 +76,8 @@ void FeedbackService::AttachedFileCallback(scoped_ptr<std::string> data) { CompleteSendFeedback(); } -void FeedbackService::ScreenshotCallback(scoped_ptr<std::string> data) { +void FeedbackService::ScreenshotCallback(scoped_ptr<std::string> data, + int64 /* total_blob_length */) { if (!data.get()) feedback_data_->set_screenshot_uuid(std::string()); else diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service.h b/chrome/browser/extensions/api/feedback_private/feedback_service.h index 9886149..3daff71 100644 --- a/chrome/browser/extensions/api/feedback_private/feedback_service.h +++ b/chrome/browser/extensions/api/feedback_private/feedback_service.h @@ -57,8 +57,10 @@ class FeedbackService { virtual base::WeakPtr<FeedbackService> GetWeakPtr() = 0; // Callbacks to receive blob data. - void AttachedFileCallback(scoped_ptr<std::string> data); - void ScreenshotCallback(scoped_ptr<std::string> data); + void AttachedFileCallback(scoped_ptr<std::string> data, + int64 total_blob_length); + void ScreenshotCallback(scoped_ptr<std::string> data, + int64 total_blob_length); // Checks if we have read all the blobs we need to; signals the feedback // data object once all the requisite data has been populated. diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc index 7d8a98f..0f12528 100644 --- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc +++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc @@ -558,7 +558,8 @@ void MediaGalleriesGetMetadataFunction::OnPreferencesInit( } void MediaGalleriesGetMetadataFunction::SniffMimeType( - bool mime_type_only, scoped_ptr<std::string> blob_header) { + bool mime_type_only, scoped_ptr<std::string> blob_header, + int64 /* total_blob_length */) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); MediaGalleries::MediaMetadata metadata; diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.h b/chrome/browser/extensions/api/media_galleries/media_galleries_api.h index 9918704..121eba1 100644 --- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.h +++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.h @@ -125,7 +125,8 @@ class MediaGalleriesGetMetadataFunction : public ChromeAsyncExtensionFunction { // Bottom half for RunImpl, invoked after the preferences is initialized. void OnPreferencesInit(bool mime_type_only, const std::string& blob_uuid); - void SniffMimeType(bool mime_type_only, scoped_ptr<std::string> blob_header); + void SniffMimeType(bool mime_type_only, scoped_ptr<std::string> blob_header, + int64 total_blob_length); }; } // namespace extensions diff --git a/chrome/browser/extensions/blob_reader.cc b/chrome/browser/extensions/blob_reader.cc index 0cfe187..ce20754 100644 --- a/chrome/browser/extensions/blob_reader.cc +++ b/chrome/browser/extensions/blob_reader.cc @@ -10,6 +10,7 @@ #include "chrome/browser/profiles/profile.h" #include "content/public/browser/browser_thread.h" #include "net/http/http_request_headers.h" +#include "net/http/http_response_headers.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" @@ -55,8 +56,10 @@ void BlobReader::Start() { // Overridden from net::URLFetcherDelegate. void BlobReader::OnURLFetchComplete(const net::URLFetcher* source) { scoped_ptr<std::string> response(new std::string); + int64 first = 0, last = 0, length = 0; source->GetResponseAsString(response.get()); - callback_.Run(response.Pass()); + source->GetResponseHeaders()->GetContentRange(&first, &last, &length); + callback_.Run(response.Pass(), length); delete this; } diff --git a/chrome/browser/extensions/blob_reader.h b/chrome/browser/extensions/blob_reader.h index 45d011d..a586571 100644 --- a/chrome/browser/extensions/blob_reader.h +++ b/chrome/browser/extensions/blob_reader.h @@ -21,7 +21,11 @@ class URLFetcher; class BlobReader : public net::URLFetcherDelegate { public: - typedef base::Callback<void(scoped_ptr<std::string> blob_data)> + // |blob_data| contains the portion of the Blob requested. |blob_total_size| + // is the total size of the Blob, and may be larger than |blob_data->size()|. + // |blob_total_size| is -1 if it cannot be determined. + typedef base::Callback<void(scoped_ptr<std::string> blob_data, + int64 blob_total_size)> BlobReadCallback; BlobReader(Profile* profile, diff --git a/chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.cc b/chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.cc index df662da..5489c7c 100644 --- a/chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.cc +++ b/chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.cc @@ -20,7 +20,8 @@ namespace { void OnBlobReaderDone( const base::WeakPtr<content::UtilityProcessHost>& utility_process_host, int64 request_id, - scoped_ptr<std::string> data) { + scoped_ptr<std::string> data, + int64 /* blob_total_size */) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (!utility_process_host.get()) diff --git a/content/browser/fileapi/blob_url_request_job_unittest.cc b/content/browser/fileapi/blob_url_request_job_unittest.cc index fe7d586..cd29aaf 100644 --- a/content/browser/fileapi/blob_url_request_job_unittest.cc +++ b/content/browser/fileapi/blob_url_request_job_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/basictypes.h" #include "base/bind.h" #include "base/file_util.h" #include "base/files/file_path.h" @@ -9,6 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/run_loop.h" +#include "base/safe_numerics.h" #include "base/time/time.h" #include "content/public/test/test_file_system_context.h" #include "net/base/io_buffer.h" @@ -225,10 +227,13 @@ class BlobURLRequestJobTest : public testing::Test { file_system_root_url_ = root; } - void TestSuccessRequest(const std::string& expected_response) { + void TestSuccessNonrangeRequest(const std::string& expected_response, + int64 expected_content_length) { expected_status_code_ = 200; expected_response_ = expected_response; TestRequest("GET", net::HttpRequestHeaders()); + EXPECT_EQ(expected_content_length, + request_->response_headers()->GetContentLength()); } void TestErrorRequest(int expected_status_code) { @@ -272,6 +277,20 @@ class BlobURLRequestJobTest : public testing::Test { *expected_result += std::string(kTestFileSystemFileData2 + 6, 7); } + // This only works if all the Blob items have a definite pre-computed length. + // Otherwise, this will fail a CHECK. + int64 GetTotalBlobLength() const { + int64 total = 0; + const std::vector<BlobData::Item>& items = blob_data_->items(); + for (std::vector<BlobData::Item>::const_iterator it = items.begin(); + it != items.end(); ++it) { + int64 length = base::checked_numeric_cast<int64>(it->length()); + CHECK(length <= kint64max - total); + total += length; + } + return total; + } + protected: base::ScopedTempDir temp_dir_; base::FilePath temp_file1_; @@ -298,12 +317,12 @@ class BlobURLRequestJobTest : public testing::Test { TEST_F(BlobURLRequestJobTest, TestGetSimpleDataRequest) { blob_data_->AppendData(kTestData1); - TestSuccessRequest(kTestData1); + TestSuccessNonrangeRequest(kTestData1, arraysize(kTestData1) - 1); } TEST_F(BlobURLRequestJobTest, TestGetSimpleFileRequest) { blob_data_->AppendFile(temp_file1_, 0, -1, base::Time()); - TestSuccessRequest(kTestFileData1); + TestSuccessNonrangeRequest(kTestFileData1, arraysize(kTestFileData1) - 1); } TEST_F(BlobURLRequestJobTest, TestGetLargeFileRequest) { @@ -317,7 +336,7 @@ TEST_F(BlobURLRequestJobTest, TestGetLargeFileRequest) { file_util::WriteFile(large_temp_file, large_data.data(), large_data.size())); blob_data_->AppendFile(large_temp_file, 0, -1, base::Time()); - TestSuccessRequest(large_data); + TestSuccessNonrangeRequest(large_data, large_data.size()); } TEST_F(BlobURLRequestJobTest, TestGetNonExistentFileRequest) { @@ -337,14 +356,15 @@ TEST_F(BlobURLRequestJobTest, TestGetChangedFileRequest) { TEST_F(BlobURLRequestJobTest, TestGetSlicedFileRequest) { blob_data_->AppendFile(temp_file1_, 2, 4, temp_file_modification_time1_); std::string result(kTestFileData1 + 2, 4); - TestSuccessRequest(result); + TestSuccessNonrangeRequest(result, 4); } TEST_F(BlobURLRequestJobTest, TestGetSimpleFileSystemFileRequest) { SetUpFileSystem(); blob_data_->AppendFileSystemFile(temp_file_system_file1_, 0, -1, - base::Time()); - TestSuccessRequest(kTestFileSystemFileData1); + base::Time()); + TestSuccessNonrangeRequest(kTestFileSystemFileData1, + arraysize(kTestFileSystemFileData1) - 1); } TEST_F(BlobURLRequestJobTest, TestGetLargeFileSystemFileRequest) { @@ -357,9 +377,9 @@ TEST_F(BlobURLRequestJobTest, TestGetLargeFileSystemFileRequest) { const char kFilename[] = "LargeBlob.dat"; WriteFileSystemFile(kFilename, large_data.data(), large_data.size(), NULL); - blob_data_->AppendFileSystemFile(GetFileSystemURL(kFilename), - 0, -1, base::Time()); - TestSuccessRequest(large_data); + blob_data_->AppendFileSystemFile(GetFileSystemURL(kFilename), 0, -1, + base::Time()); + TestSuccessNonrangeRequest(large_data, large_data.size()); } TEST_F(BlobURLRequestJobTest, TestGetNonExistentFileSystemFileRequest) { @@ -383,14 +403,14 @@ TEST_F(BlobURLRequestJobTest, TestGetSlicedFileSystemFileRequest) { blob_data_->AppendFileSystemFile(temp_file_system_file1_, 2, 4, temp_file_system_file_modification_time1_); std::string result(kTestFileSystemFileData1 + 2, 4); - TestSuccessRequest(result); + TestSuccessNonrangeRequest(result, 4); } TEST_F(BlobURLRequestJobTest, TestGetComplicatedDataAndFileRequest) { SetUpFileSystem(); std::string result; BuildComplicatedData(&result); - TestSuccessRequest(result); + TestSuccessNonrangeRequest(result, GetTotalBlobLength()); } TEST_F(BlobURLRequestJobTest, TestGetRangeRequest1) { @@ -403,6 +423,15 @@ TEST_F(BlobURLRequestJobTest, TestGetRangeRequest1) { expected_status_code_ = 206; expected_response_ = result.substr(5, 10 - 5 + 1); TestRequest("GET", extra_headers); + + EXPECT_EQ(6, request_->response_headers()->GetContentLength()); + + int64 first = 0, last = 0, length = 0; + EXPECT_TRUE( + request_->response_headers()->GetContentRange(&first, &last, &length)); + EXPECT_EQ(5, first); + EXPECT_EQ(10, last); + EXPECT_EQ(GetTotalBlobLength(), length); } TEST_F(BlobURLRequestJobTest, TestGetRangeRequest2) { @@ -415,6 +444,16 @@ TEST_F(BlobURLRequestJobTest, TestGetRangeRequest2) { expected_status_code_ = 206; expected_response_ = result.substr(result.length() - 10); TestRequest("GET", extra_headers); + + EXPECT_EQ(10, request_->response_headers()->GetContentLength()); + + int64 total = GetTotalBlobLength(); + int64 first = 0, last = 0, length = 0; + EXPECT_TRUE( + request_->response_headers()->GetContentRange(&first, &last, &length)); + EXPECT_EQ(total - 10, first); + EXPECT_EQ(total - 1, last); + EXPECT_EQ(total, length); } TEST_F(BlobURLRequestJobTest, TestExtraHeaders) { diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index 9d95153..52bdfd7 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc @@ -115,6 +115,8 @@ void CheckDoesNotHaveEmbededNulls(const std::string& str) { } // namespace +const char HttpResponseHeaders::kContentRange[] = "Content-Range"; + struct HttpResponseHeaders::ParsedHeader { // A header "continuation" contains only a subsequent value for the // preceding header. (Header values are comma separated.) @@ -819,7 +821,7 @@ void HttpResponseHeaders::AddChallengeHeaders(HeaderSet* result) { } void HttpResponseHeaders::AddHopContentRangeHeaders(HeaderSet* result) { - result->insert("content-range"); + result->insert(kContentRange); } void HttpResponseHeaders::AddSecurityStateHeaders(HeaderSet* result) { @@ -1199,7 +1201,7 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position, void* iter = NULL; std::string content_range_spec; *first_byte_position = *last_byte_position = *instance_length = -1; - if (!EnumerateHeader(&iter, "content-range", &content_range_spec)) + if (!EnumerateHeader(&iter, kContentRange, &content_range_spec)) return false; // If the header value is empty, we have an invalid header. diff --git a/net/http/http_response_headers.h b/net/http/http_response_headers.h index e54ac5d..6a5dc83 100644 --- a/net/http/http_response_headers.h +++ b/net/http/http_response_headers.h @@ -41,6 +41,8 @@ class NET_EXPORT HttpResponseHeaders static const PersistOptions PERSIST_SANS_RANGES = 1 << 4; static const PersistOptions PERSIST_SANS_SECURITY_STATE = 1 << 5; + static const char kContentRange[]; + // Parses the given raw_headers. raw_headers should be formatted thus: // includes the http status response line, each line is \0-terminated, and // it's terminated by an empty line (ie, 2 \0s in a row). diff --git a/webkit/browser/blob/blob_url_request_job.cc b/webkit/browser/blob/blob_url_request_job.cc index 4b89636..f1040f5 100644 --- a/webkit/browser/blob/blob_url_request_job.cc +++ b/webkit/browser/blob/blob_url_request_job.cc @@ -10,10 +10,12 @@ #include "base/bind.h" #include "base/compiler_specific.h" #include "base/files/file_util_proxy.h" +#include "base/format_macros.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/http/http_request_headers.h" @@ -509,6 +511,18 @@ void BlobURLRequestJob::HeadersCompleted(net::HttpStatusCode status_code) { content_length_header.append(": "); content_length_header.append(base::Int64ToString(remaining_bytes_)); headers->AddHeader(content_length_header); + if (status_code == net::HTTP_PARTIAL_CONTENT) { + DCHECK(byte_range_set_); + DCHECK(byte_range_.IsValid()); + std::string content_range_header(net::HttpResponseHeaders::kContentRange); + content_range_header.append(": bytes "); + content_range_header.append(base::StringPrintf( + "%" PRId64 "-%" PRId64, + byte_range_.first_byte_position(), byte_range_.last_byte_position())); + content_range_header.append("/"); + content_range_header.append(base::StringPrintf("%" PRId64, total_size_)); + headers->AddHeader(content_range_header); + } if (!blob_data_->content_type().empty()) { std::string content_type_header(net::HttpRequestHeaders::kContentType); content_type_header.append(": "); |