summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortommycli@chromium.org <tommycli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-15 09:55:38 +0000
committertommycli@chromium.org <tommycli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-15 09:55:38 +0000
commit89b429341068c7b6d4c1129052e7abfc708d6161 (patch)
tree208aa003365726a6ae615da869b9ab19dc451c09
parent24e4cac9b53c6bebf0bafc40213ff67fa9caedb2 (diff)
downloadchromium_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
-rw-r--r--chrome/browser/extensions/api/feedback_private/feedback_service.cc6
-rw-r--r--chrome/browser/extensions/api/feedback_private/feedback_service.h6
-rw-r--r--chrome/browser/extensions/api/media_galleries/media_galleries_api.cc3
-rw-r--r--chrome/browser/extensions/api/media_galleries/media_galleries_api.h3
-rw-r--r--chrome/browser/extensions/blob_reader.cc5
-rw-r--r--chrome/browser/extensions/blob_reader.h6
-rw-r--r--chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.cc3
-rw-r--r--content/browser/fileapi/blob_url_request_job_unittest.cc63
-rw-r--r--net/http/http_response_headers.cc6
-rw-r--r--net/http/http_response_headers.h2
-rw-r--r--webkit/browser/blob/blob_url_request_job.cc14
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(": ");