Commit aba8000c authored by Matt Menke's avatar Matt Menke Committed by Commit Bot

Add a DataElement::TYPE_RAW_FILE type that contains a file handle.

This, or something like it, will eventually need to replace TYPE_FILE
(Which just contains a path) in order to sandbox the network service
process.

Bug: 777879
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo
Change-Id: I8c67e828288443cbfc15aa774c1b97aa2f22ef29
Reviewed-on: https://chromium-review.googlesource.com/773238
Commit-Queue: Matt Menke <mmenke@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarMarijn Kruisselbrink <mek@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#518390}
parent 9984945d
...@@ -170,6 +170,7 @@ void BlobDispatcherHost::OnRegisterBlob( ...@@ -170,6 +170,7 @@ void BlobDispatcherHost::OnRegisterBlob(
// originally created by other processes? If so, is that cool? // originally created by other processes? If so, is that cool?
break; break;
} }
case storage::DataElement::TYPE_RAW_FILE:
case storage::DataElement::TYPE_UNKNOWN: case storage::DataElement::TYPE_UNKNOWN:
case storage::DataElement::TYPE_DATA_PIPE: case storage::DataElement::TYPE_DATA_PIPE:
case storage::DataElement::TYPE_DISK_CACHE_ENTRY: { case storage::DataElement::TYPE_DISK_CACHE_ENTRY: {
......
...@@ -111,6 +111,7 @@ std::unique_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build( ...@@ -111,6 +111,7 @@ std::unique_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM: case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
CHECK(false) << "Should never be reached"; CHECK(false) << "Should never be reached";
break; break;
case ResourceRequestBody::Element::TYPE_RAW_FILE:
case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY:
case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION: case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION:
case ResourceRequestBody::Element::TYPE_DATA_PIPE: case ResourceRequestBody::Element::TYPE_DATA_PIPE:
......
...@@ -453,6 +453,7 @@ void WriteResourceRequestBody(const ResourceRequestBody& request_body, ...@@ -453,6 +453,7 @@ void WriteResourceRequestBody(const ResourceRequestBody& request_body,
WriteInteger(blink::WebHTTPBody::Element::kTypeBlob, obj); WriteInteger(blink::WebHTTPBody::Element::kTypeBlob, obj);
WriteStdString(element.blob_uuid(), obj); WriteStdString(element.blob_uuid(), obj);
break; break;
case ResourceRequestBody::Element::TYPE_RAW_FILE:
case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION: case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION:
case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY:
default: default:
...@@ -744,6 +745,7 @@ void WriteResourceRequestBody(const ResourceRequestBody& request_body, ...@@ -744,6 +745,7 @@ void WriteResourceRequestBody(const ResourceRequestBody& request_body,
case ResourceRequestBody::Element::TYPE_BLOB: case ResourceRequestBody::Element::TYPE_BLOB:
data_element->set_blob_uuid(element.blob_uuid()); data_element->set_blob_uuid(element.blob_uuid());
break; break;
case ResourceRequestBody::Element::TYPE_RAW_FILE:
case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION: case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION:
case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY:
case ResourceRequestBody::Element::TYPE_DATA_PIPE: case ResourceRequestBody::Element::TYPE_DATA_PIPE:
......
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
#include "content/common/resource_messages.h" #include "content/common/resource_messages.h"
#include "base/files/file.h"
#include "base/files/platform_file.h"
#include "ipc/ipc_mojo_param_traits.h" #include "ipc/ipc_mojo_param_traits.h"
#include "ipc/ipc_platform_file.h"
#include "net/base/load_timing_info.h" #include "net/base/load_timing_info.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
...@@ -154,6 +157,16 @@ void ParamTraits<storage::DataElement>::Write(base::Pickle* m, ...@@ -154,6 +157,16 @@ void ParamTraits<storage::DataElement>::Write(base::Pickle* m,
WriteParam(m, p.expected_modification_time()); WriteParam(m, p.expected_modification_time());
break; break;
} }
case storage::DataElement::TYPE_RAW_FILE: {
WriteParam(
m, IPC::GetPlatformFileForTransit(p.file().GetPlatformFile(),
false /* close_source_handle */));
WriteParam(m, p.path());
WriteParam(m, p.offset());
WriteParam(m, p.length());
WriteParam(m, p.expected_modification_time());
break;
}
case storage::DataElement::TYPE_FILE_FILESYSTEM: { case storage::DataElement::TYPE_FILE_FILESYSTEM: {
WriteParam(m, p.filesystem_url()); WriteParam(m, p.filesystem_url());
WriteParam(m, p.offset()); WriteParam(m, p.offset());
...@@ -224,6 +237,27 @@ bool ParamTraits<storage::DataElement>::Read(const base::Pickle* m, ...@@ -224,6 +237,27 @@ bool ParamTraits<storage::DataElement>::Read(const base::Pickle* m,
expected_modification_time); expected_modification_time);
return true; return true;
} }
case storage::DataElement::TYPE_RAW_FILE: {
IPC::PlatformFileForTransit platform_file_for_transit;
if (!ReadParam(m, iter, &platform_file_for_transit))
return false;
base::File file = PlatformFileForTransitToFile(platform_file_for_transit);
base::FilePath file_path;
if (!ReadParam(m, iter, &file_path))
return false;
uint64_t offset;
if (!ReadParam(m, iter, &offset))
return false;
uint64_t length;
if (!ReadParam(m, iter, &length))
return false;
base::Time expected_modification_time;
if (!ReadParam(m, iter, &expected_modification_time))
return false;
r->SetToFileRange(std::move(file), file_path, offset, length,
expected_modification_time);
return true;
}
case storage::DataElement::TYPE_FILE_FILESYSTEM: { case storage::DataElement::TYPE_FILE_FILESYSTEM: {
GURL file_system_url; GURL file_system_url;
uint64_t offset, length; uint64_t offset, length;
......
...@@ -15,6 +15,7 @@ include_rules = [ ...@@ -15,6 +15,7 @@ include_rules = [
"+content/public/common/network_service.mojom.h", "+content/public/common/network_service.mojom.h",
"+content/public/common/referrer.h", "+content/public/common/referrer.h",
"+content/public/common/resource_request.h", "+content/public/common/resource_request.h",
"+content/public/common/resource_request_body.h",
"+content/public/common/resource_response.h", "+content/public/common/resource_response.h",
"+content/public/common/url_constants.h", "+content/public/common/url_constants.h",
"+content/public/common/url_loader.mojom.h", "+content/public/common/url_loader.mojom.h",
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <string> #include <string>
#include "base/files/file.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/task_scheduler/post_task.h" #include "base/task_scheduler/post_task.h"
...@@ -15,6 +16,8 @@ ...@@ -15,6 +16,8 @@
#include "content/network/network_context.h" #include "content/network/network_context.h"
#include "content/network/network_service_impl.h" #include "content/network/network_service_impl.h"
#include "content/public/common/referrer.h" #include "content/public/common/referrer.h"
#include "content/public/common/resource_request.h"
#include "content/public/common/resource_request_body.h"
#include "content/public/common/resource_response.h" #include "content/public/common/resource_response.h"
#include "content/public/common/url_loader_factory.mojom.h" #include "content/public/common/url_loader_factory.mojom.h"
#include "mojo/public/cpp/system/simple_watcher.h" #include "mojo/public/cpp/system/simple_watcher.h"
...@@ -140,6 +143,31 @@ class FileElementReader : public net::UploadFileElementReader { ...@@ -140,6 +143,31 @@ class FileElementReader : public net::UploadFileElementReader {
DISALLOW_COPY_AND_ASSIGN(FileElementReader); DISALLOW_COPY_AND_ASSIGN(FileElementReader);
}; };
class RawFileElementReader : public net::UploadFileElementReader {
public:
RawFileElementReader(ResourceRequestBody* resource_request_body,
base::TaskRunner* task_runner,
const ResourceRequestBody::Element& element)
: net::UploadFileElementReader(
task_runner,
// TODO(mmenke): Is duplicating this necessary?
element.file().Duplicate(),
element.path(),
element.offset(),
element.length(),
element.expected_modification_time()),
resource_request_body_(resource_request_body) {
DCHECK_EQ(ResourceRequestBody::Element::TYPE_RAW_FILE, element.type());
}
~RawFileElementReader() override {}
private:
scoped_refptr<ResourceRequestBody> resource_request_body_;
DISALLOW_COPY_AND_ASSIGN(RawFileElementReader);
};
// A subclass of net::UploadElementReader to read data pipes. // A subclass of net::UploadElementReader to read data pipes.
class DataPipeElementReader : public net::UploadElementReader { class DataPipeElementReader : public net::UploadElementReader {
public: public:
...@@ -247,6 +275,10 @@ std::unique_ptr<net::UploadDataStream> CreateUploadDataStream( ...@@ -247,6 +275,10 @@ std::unique_ptr<net::UploadDataStream> CreateUploadDataStream(
element_readers.push_back(std::make_unique<FileElementReader>( element_readers.push_back(std::make_unique<FileElementReader>(
body, file_task_runner, element)); body, file_task_runner, element));
break; break;
case ResourceRequestBody::Element::TYPE_RAW_FILE:
element_readers.push_back(std::make_unique<RawFileElementReader>(
body, file_task_runner, element));
break;
case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM: case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
CHECK(false) << "Should never be reached"; CHECK(false) << "Should never be reached";
break; break;
......
...@@ -2,26 +2,37 @@ ...@@ -2,26 +2,37 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <stdint.h>
#include <limits>
#include <list> #include <list>
#include <memory> #include <memory>
#include <string> #include <string>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/scoped_task_environment.h" #include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/network/network_context.h" #include "content/network/network_context.h"
#include "content/network/url_loader.h" #include "content/network/url_loader.h"
#include "content/public/common/appcache_info.h" #include "content/public/common/appcache_info.h"
#include "content/public/common/content_paths.h" #include "content/public/common/content_paths.h"
#include "content/public/common/resource_request.h"
#include "content/public/common/resource_request_body.h"
#include "content/public/test/controllable_http_response.h" #include "content/public/test/controllable_http_response.h"
#include "content/public/test/test_url_loader_client.h" #include "content/public/test/test_url_loader_client.h"
#include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/cpp/system/wait.h" #include "mojo/public/cpp/system/wait.h"
#include "net/base/io_buffer.h" #include "net/base/io_buffer.h"
#include "net/base/mime_sniffer.h" #include "net/base/mime_sniffer.h"
#include "net/base/net_errors.h"
#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_response.h" #include "net/test/embedded_test_server/http_response.h"
#include "net/test/url_request/url_request_failed_job.h" #include "net/test/url_request/url_request_failed_job.h"
...@@ -32,6 +43,7 @@ ...@@ -32,6 +43,7 @@
#include "net/url_request/url_request_job.h" #include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_status.h" #include "net/url_request/url_request_status.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content { namespace content {
...@@ -177,7 +189,8 @@ class URLLoaderTest : public testing::Test { ...@@ -177,7 +189,8 @@ class URLLoaderTest : public testing::Test {
DCHECK(!ran_); DCHECK(!ran_);
mojom::URLLoaderPtr loader; mojom::URLLoaderPtr loader;
ResourceRequest request = CreateResourceRequest("GET", resource_type_, url); ResourceRequest request = CreateResourceRequest(
!request_body_ ? "GET" : "POST", resource_type_, url);
uint32_t options = mojom::kURLLoadOptionNone; uint32_t options = mojom::kURLLoadOptionNone;
if (send_ssl_) if (send_ssl_)
options |= mojom::kURLLoadOptionSendSSLInfo; options |= mojom::kURLLoadOptionSendSSLInfo;
...@@ -186,6 +199,9 @@ class URLLoaderTest : public testing::Test { ...@@ -186,6 +199,9 @@ class URLLoaderTest : public testing::Test {
if (add_custom_accept_header_) if (add_custom_accept_header_)
request.headers.SetHeader("accept", "custom/*"); request.headers.SetHeader("accept", "custom/*");
if (request_body_)
request.request_body = request_body_;
URLLoader loader_impl(context(), mojo::MakeRequest(&loader), options, URLLoader loader_impl(context(), mojo::MakeRequest(&loader), options,
request, false, client_.CreateInterfacePtr(), request, false, client_.CreateInterfacePtr(),
TRAFFIC_ANNOTATION_FOR_TESTS, 0); TRAFFIC_ANNOTATION_FOR_TESTS, 0);
...@@ -208,9 +224,7 @@ class URLLoaderTest : public testing::Test { ...@@ -208,9 +224,7 @@ class URLLoaderTest : public testing::Test {
} }
void LoadAndCompareFile(const std::string& path) { void LoadAndCompareFile(const std::string& path) {
base::FilePath file; base::FilePath file = GetTestFilePath(path);
PathService::Get(content::DIR_TEST_DATA, &file);
file = file.AppendASCII(path);
std::string expected; std::string expected;
if (!base::ReadFileToString(file, &expected)) { if (!base::ReadFileToString(file, &expected)) {
...@@ -276,6 +290,23 @@ class URLLoaderTest : public testing::Test { ...@@ -276,6 +290,23 @@ class URLLoaderTest : public testing::Test {
TestURLLoaderClient* client() { return &client_; } TestURLLoaderClient* client() { return &client_; }
void DestroyContext() { context_.reset(); } void DestroyContext() { context_.reset(); }
// Returns the path of the requested file in the test data directory.
base::FilePath GetTestFilePath(const std::string& file_name) {
base::FilePath file_path;
PathService::Get(DIR_TEST_DATA, &file_path);
return file_path.AppendASCII(file_name);
}
base::File OpenFileForUpload(const base::FilePath& file_path) {
int open_flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
#if defined(OS_WIN)
open_flags |= base::File::FLAG_ASYNC;
#endif // defined(OS_WIN)
base::File file(file_path, open_flags);
EXPECT_TRUE(file.IsValid());
return file;
}
// Configure how Load() works. // Configure how Load() works.
void set_sniff() { void set_sniff() {
DCHECK(!ran_); DCHECK(!ran_);
...@@ -293,6 +324,9 @@ class URLLoaderTest : public testing::Test { ...@@ -293,6 +324,9 @@ class URLLoaderTest : public testing::Test {
DCHECK(!ran_); DCHECK(!ran_);
resource_type_ = type; resource_type_ = type;
} }
void set_request_body(scoped_refptr<ResourceRequestBody> request_body) {
request_body_ = request_body;
}
// Convenience methods after calling Load(); // Convenience methods after calling Load();
std::string mime_type() const { std::string mime_type() const {
...@@ -378,10 +412,14 @@ class URLLoaderTest : public testing::Test { ...@@ -378,10 +412,14 @@ class URLLoaderTest : public testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_; base::test::ScopedTaskEnvironment scoped_task_environment_;
net::EmbeddedTestServer test_server_; net::EmbeddedTestServer test_server_;
std::unique_ptr<NetworkContext> context_; std::unique_ptr<NetworkContext> context_;
// Options applied the created request in Load().
bool sniff_ = false; bool sniff_ = false;
bool send_ssl_ = false; bool send_ssl_ = false;
bool add_custom_accept_header_ = false; bool add_custom_accept_header_ = false;
ResourceType resource_type_ = RESOURCE_TYPE_MAIN_FRAME; ResourceType resource_type_ = RESOURCE_TYPE_MAIN_FRAME;
scoped_refptr<ResourceRequestBody> request_body_;
// Used to ensure that methods are called either before or after a request is // Used to ensure that methods are called either before or after a request is
// made, since the test fixture is meant to be used only once. // made, since the test fixture is meant to be used only once.
bool ran_ = false; bool ran_ = false;
...@@ -907,4 +945,111 @@ TEST_F(URLLoaderTest, DoNotOverrideAcceptHeader) { ...@@ -907,4 +945,111 @@ TEST_F(URLLoaderTest, DoNotOverrideAcceptHeader) {
EXPECT_EQ(it->second, "custom/*"); EXPECT_EQ(it->second, "custom/*");
} }
TEST_F(URLLoaderTest, UploadBytes) {
const std::string kRequestBody = "Request Body";
scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
request_body->AppendBytes(kRequestBody.c_str(), kRequestBody.length());
set_request_body(std::move(request_body));
std::string response_body;
EXPECT_EQ(net::OK, Load(test_server()->GetURL("/echo"), &response_body));
EXPECT_EQ(kRequestBody, response_body);
}
TEST_F(URLLoaderTest, UploadFile) {
base::FilePath file_path = GetTestFilePath("simple_page.html");
std::string expected_body;
ASSERT_TRUE(base::ReadFileToString(file_path, &expected_body))
<< "File not found: " << file_path.value();
scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
request_body->AppendFileRange(
file_path, 0, std::numeric_limits<uint64_t>::max(), base::Time());
set_request_body(std::move(request_body));
std::string response_body;
EXPECT_EQ(net::OK, Load(test_server()->GetURL("/echo"), &response_body));
EXPECT_EQ(expected_body, response_body);
}
TEST_F(URLLoaderTest, UploadFileWithRange) {
base::FilePath file_path = GetTestFilePath("simple_page.html");
std::string expected_body;
ASSERT_TRUE(base::ReadFileToString(file_path, &expected_body))
<< "File not found: " << file_path.value();
expected_body = expected_body.substr(1, expected_body.size() - 2);
scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
request_body->AppendFileRange(file_path, 1, expected_body.size(),
base::Time());
set_request_body(std::move(request_body));
std::string response_body;
EXPECT_EQ(net::OK, Load(test_server()->GetURL("/echo"), &response_body));
EXPECT_EQ(expected_body, response_body);
}
TEST_F(URLLoaderTest, UploadRawFile) {
base::FilePath file_path = GetTestFilePath("simple_page.html");
std::string expected_body;
ASSERT_TRUE(base::ReadFileToString(file_path, &expected_body))
<< "File not found: " << file_path.value();
scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
request_body->AppendRawFileRange(
OpenFileForUpload(file_path), GetTestFilePath("should_be_ignored"), 0,
std::numeric_limits<uint64_t>::max(), base::Time());
set_request_body(std::move(request_body));
std::string response_body;
EXPECT_EQ(net::OK, Load(test_server()->GetURL("/echo"), &response_body));
EXPECT_EQ(expected_body, response_body);
}
TEST_F(URLLoaderTest, UploadRawFileWithRange) {
base::FilePath file_path = GetTestFilePath("simple_page.html");
std::string expected_body;
ASSERT_TRUE(base::ReadFileToString(file_path, &expected_body))
<< "File not found: " << file_path.value();
expected_body = expected_body.substr(1, expected_body.size() - 2);
scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
request_body->AppendRawFileRange(OpenFileForUpload(file_path),
GetTestFilePath("should_be_ignored"), 1,
expected_body.size(), base::Time());
set_request_body(std::move(request_body));
std::string response_body;
EXPECT_EQ(net::OK, Load(test_server()->GetURL("/echo"), &response_body));
EXPECT_EQ(expected_body, response_body);
}
// TODO(mmenke): Test using a data pipe to upload data.
TEST_F(URLLoaderTest, UploadDoubleRawFile) {
base::FilePath file_path = GetTestFilePath("simple_page.html");
std::string expected_body;
ASSERT_TRUE(base::ReadFileToString(file_path, &expected_body))
<< "File not found: " << file_path.value();
scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
request_body->AppendRawFileRange(
OpenFileForUpload(file_path), GetTestFilePath("should_be_ignored"), 0,
std::numeric_limits<uint64_t>::max(), base::Time());
request_body->AppendRawFileRange(
OpenFileForUpload(file_path), GetTestFilePath("should_be_ignored"), 0,
std::numeric_limits<uint64_t>::max(), base::Time());
set_request_body(std::move(request_body));
std::string response_body;
EXPECT_EQ(net::OK, Load(test_server()->GetURL("/echo"), &response_body));
EXPECT_EQ(expected_body + expected_body, response_body);
}
} // namespace content } // namespace content
...@@ -54,6 +54,17 @@ void ResourceRequestBody::AppendFileRange( ...@@ -54,6 +54,17 @@ void ResourceRequestBody::AppendFileRange(
expected_modification_time); expected_modification_time);
} }
void ResourceRequestBody::AppendRawFileRange(
base::File file,
const base::FilePath& file_path,
uint64_t offset,
uint64_t length,
const base::Time& expected_modification_time) {
elements_.push_back(Element());
elements_.back().SetToFileRange(std::move(file), file_path, offset, length,
expected_modification_time);
}
void ResourceRequestBody::AppendBlob(const std::string& uuid) { void ResourceRequestBody::AppendBlob(const std::string& uuid) {
elements_.push_back(Element()); elements_.push_back(Element());
elements_.back().SetToBlob(uuid); elements_.back().SetToBlob(uuid);
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -54,6 +56,13 @@ class CONTENT_EXPORT ResourceRequestBody ...@@ -54,6 +56,13 @@ class CONTENT_EXPORT ResourceRequestBody
uint64_t offset, uint64_t offset,
uint64_t length, uint64_t length,
const base::Time& expected_modification_time); const base::Time& expected_modification_time);
// Appends the specified part of |file|. If |length| extends beyond the end of
// the file, it will be set to the end of the file.
void AppendRawFileRange(base::File file,
const base::FilePath& file_path,
uint64_t offset,
uint64_t length,
const base::Time& expected_modification_time);
void AppendBlob(const std::string& uuid); void AppendBlob(const std::string& uuid);
void AppendFileSystemFileRange(const GURL& url, void AppendFileSystemFileRange(const GURL& url,
......
...@@ -368,6 +368,7 @@ void BlobTransportController::GetDescriptions( ...@@ -368,6 +368,7 @@ void BlobTransportController::GetDescriptions(
base::Time::FromDoubleT(item.expected_modification_time)); base::Time::FromDoubleT(item.expected_modification_time));
break; break;
} }
case DataElement::TYPE_RAW_FILE:
case DataElement::TYPE_DISK_CACHE_ENTRY: case DataElement::TYPE_DISK_CACHE_ENTRY:
case DataElement::TYPE_BYTES_DESCRIPTION: case DataElement::TYPE_BYTES_DESCRIPTION:
case DataElement::TYPE_DATA_PIPE: case DataElement::TYPE_DATA_PIPE:
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "base/files/file.h"
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "base/numerics/safe_math.h" #include "base/numerics/safe_math.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
...@@ -83,6 +84,7 @@ void BlobDataBuilder::AppendIPCDataElement(const DataElement& ipc_data) { ...@@ -83,6 +84,7 @@ void BlobDataBuilder::AppendIPCDataElement(const DataElement& ipc_data) {
// BlobStorageContext. // BlobStorageContext.
AppendBlob(ipc_data.blob_uuid(), ipc_data.offset(), ipc_data.length()); AppendBlob(ipc_data.blob_uuid(), ipc_data.offset(), ipc_data.length());
break; break;
case DataElement::TYPE_RAW_FILE:
case DataElement::TYPE_BYTES_DESCRIPTION: case DataElement::TYPE_BYTES_DESCRIPTION:
case DataElement::TYPE_UNKNOWN: case DataElement::TYPE_UNKNOWN:
case DataElement::TYPE_DISK_CACHE_ENTRY: // This type can't be sent by IPC. case DataElement::TYPE_DISK_CACHE_ENTRY: // This type can't be sent by IPC.
......
...@@ -662,6 +662,7 @@ std::unique_ptr<FileStreamReader> BlobReader::CreateFileStreamReader( ...@@ -662,6 +662,7 @@ std::unique_ptr<FileStreamReader> BlobReader::CreateFileStreamReader(
? storage::kMaximumLength ? storage::kMaximumLength
: item.length() - additional_offset, : item.length() - additional_offset,
item.expected_modification_time()); item.expected_modification_time());
case DataElement::TYPE_RAW_FILE:
case DataElement::TYPE_BLOB: case DataElement::TYPE_BLOB:
case DataElement::TYPE_BYTES: case DataElement::TYPE_BYTES:
case DataElement::TYPE_BYTES_DESCRIPTION: case DataElement::TYPE_BYTES_DESCRIPTION:
......
...@@ -75,6 +75,7 @@ void RecordBlobItemSizeStats(const DataElement& input_element) { ...@@ -75,6 +75,7 @@ void RecordBlobItemSizeStats(const DataElement& input_element) {
UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.CacheEntry", UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.CacheEntry",
(length - input_element.offset()) / 1024); (length - input_element.offset()) / 1024);
break; break;
case DataElement::TYPE_RAW_FILE:
case DataElement::TYPE_DATA_PIPE: case DataElement::TYPE_DATA_PIPE:
case DataElement::TYPE_UNKNOWN: case DataElement::TYPE_UNKNOWN:
NOTREACHED(); NOTREACHED();
...@@ -369,6 +370,7 @@ BlobStorageContext::BlobSlice::BlobSlice(const BlobEntry& source, ...@@ -369,6 +370,7 @@ BlobStorageContext::BlobSlice::BlobSlice(const BlobEntry& source,
source_item->disk_cache_side_stream_index()); source_item->disk_cache_side_stream_index());
break; break;
} }
case DataElement::TYPE_RAW_FILE:
case DataElement::TYPE_BLOB: case DataElement::TYPE_BLOB:
case DataElement::TYPE_DATA_PIPE: case DataElement::TYPE_DATA_PIPE:
case DataElement::TYPE_UNKNOWN: case DataElement::TYPE_UNKNOWN:
...@@ -793,6 +795,7 @@ void BlobStorageContext::FinishBuilding(BlobEntry* entry) { ...@@ -793,6 +795,7 @@ void BlobStorageContext::FinishBuilding(BlobEntry* entry) {
copy.dest_item->set_item(std::move(new_item)); copy.dest_item->set_item(std::move(new_item));
break; break;
} }
case DataElement::TYPE_RAW_FILE:
case DataElement::TYPE_UNKNOWN: case DataElement::TYPE_UNKNOWN:
case DataElement::TYPE_BLOB: case DataElement::TYPE_BLOB:
case DataElement::TYPE_BYTES_DESCRIPTION: case DataElement::TYPE_BYTES_DESCRIPTION:
......
...@@ -282,6 +282,7 @@ void ViewBlobInternalsJob::GenerateHTMLForBlobData( ...@@ -282,6 +282,7 @@ void ViewBlobInternalsJob::GenerateHTMLForBlobData(
case DataElement::TYPE_DATA_PIPE: case DataElement::TYPE_DATA_PIPE:
AddHTMLListItem(kType, "data pipe", out); AddHTMLListItem(kType, "data pipe", out);
break; break;
case DataElement::TYPE_RAW_FILE:
case DataElement::TYPE_UNKNOWN: case DataElement::TYPE_UNKNOWN:
NOTREACHED(); NOTREACHED();
break; break;
......
...@@ -36,6 +36,19 @@ void DataElement::SetToFilePathRange( ...@@ -36,6 +36,19 @@ void DataElement::SetToFilePathRange(
expected_modification_time_ = expected_modification_time; expected_modification_time_ = expected_modification_time;
} }
void DataElement::SetToFileRange(base::File file,
const base::FilePath& path,
uint64_t offset,
uint64_t length,
const base::Time& expected_modification_time) {
type_ = TYPE_RAW_FILE;
file_ = std::move(file);
path_ = path;
offset_ = offset;
length_ = length;
expected_modification_time_ = expected_modification_time;
}
void DataElement::SetToBlobRange(const std::string& blob_uuid, void DataElement::SetToBlobRange(const std::string& blob_uuid,
uint64_t offset, uint64_t offset,
uint64_t length) { uint64_t length) {
...@@ -70,6 +83,10 @@ void DataElement::SetToDataPipe(mojo::ScopedDataPipeConsumerHandle handle, ...@@ -70,6 +83,10 @@ void DataElement::SetToDataPipe(mojo::ScopedDataPipeConsumerHandle handle,
data_pipe_size_getter_ = std::move(size_getter); data_pipe_size_getter_ = std::move(size_getter);
} }
base::File DataElement::ReleaseFile() {
return std::move(file_);
}
mojo::ScopedDataPipeConsumerHandle DataElement::ReleaseDataPipe( mojo::ScopedDataPipeConsumerHandle DataElement::ReleaseDataPipe(
blink::mojom::SizeGetterPtr* size_getter) { blink::mojom::SizeGetterPtr* size_getter) {
if (size_getter) if (size_getter)
...@@ -95,6 +112,10 @@ void PrintTo(const DataElement& x, std::ostream* os) { ...@@ -95,6 +112,10 @@ void PrintTo(const DataElement& x, std::ostream* os) {
*os << "TYPE_FILE, path: " << x.path().AsUTF8Unsafe() *os << "TYPE_FILE, path: " << x.path().AsUTF8Unsafe()
<< ", expected_modification_time: " << x.expected_modification_time(); << ", expected_modification_time: " << x.expected_modification_time();
break; break;
case DataElement::TYPE_RAW_FILE:
*os << "TYPE_RAW_FILE, path: " << x.path().AsUTF8Unsafe()
<< ", expected_modification_time: " << x.expected_modification_time();
break;
case DataElement::TYPE_BLOB: case DataElement::TYPE_BLOB:
*os << "TYPE_BLOB, uuid: " << x.blob_uuid(); *os << "TYPE_BLOB, uuid: " << x.blob_uuid();
break; break;
...@@ -127,6 +148,9 @@ bool operator==(const DataElement& a, const DataElement& b) { ...@@ -127,6 +148,9 @@ bool operator==(const DataElement& a, const DataElement& b) {
case DataElement::TYPE_FILE: case DataElement::TYPE_FILE:
return a.path() == b.path() && return a.path() == b.path() &&
a.expected_modification_time() == b.expected_modification_time(); a.expected_modification_time() == b.expected_modification_time();
case DataElement::TYPE_RAW_FILE:
return a.path() == b.path() &&
a.expected_modification_time() == b.expected_modification_time();
case DataElement::TYPE_BLOB: case DataElement::TYPE_BLOB:
return a.blob_uuid() == b.blob_uuid(); return a.blob_uuid() == b.blob_uuid();
case DataElement::TYPE_FILE_FILESYSTEM: case DataElement::TYPE_FILE_FILESYSTEM:
......
...@@ -9,10 +9,12 @@ ...@@ -9,10 +9,12 @@
#include <stdint.h> #include <stdint.h>
#include <limits> #include <limits>
#include <memory>
#include <ostream> #include <ostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/files/file.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/logging.h" #include "base/logging.h"
...@@ -32,14 +34,23 @@ class STORAGE_COMMON_EXPORT DataElement { ...@@ -32,14 +34,23 @@ class STORAGE_COMMON_EXPORT DataElement {
enum Type { enum Type {
TYPE_UNKNOWN = -1, TYPE_UNKNOWN = -1,
TYPE_BYTES,
// Only used with BlobStorageMsg_StartBuildingBlob // Only used for Upload with Network Service as of now:
TYPE_DATA_PIPE,
TYPE_RAW_FILE,
// Only used for Blob:
TYPE_BYTES_DESCRIPTION, TYPE_BYTES_DESCRIPTION,
TYPE_FILE, TYPE_DISK_CACHE_ENTRY, // Only used by CacheStorage
TYPE_BLOB, // Used in ResourceDispatcherHost path.
TYPE_FILE_FILESYSTEM, TYPE_FILE_FILESYSTEM,
TYPE_DISK_CACHE_ENTRY,
TYPE_DATA_PIPE, // Used in Network Service path. // Commonly used for Blob, and also for Upload when Network Service is
// disabled:
TYPE_BLOB, // Used old IPC codepath only.
TYPE_FILE,
// Commonly used in every case:
TYPE_BYTES,
}; };
DataElement(); DataElement();
...@@ -53,6 +64,7 @@ class STORAGE_COMMON_EXPORT DataElement { ...@@ -53,6 +64,7 @@ class STORAGE_COMMON_EXPORT DataElement {
Type type() const { return type_; } Type type() const { return type_; }
const char* bytes() const { return bytes_ ? bytes_ : buf_.data(); } const char* bytes() const { return bytes_ ? bytes_ : buf_.data(); }
const base::FilePath& path() const { return path_; } const base::FilePath& path() const { return path_; }
const base::File& file() const { return file_; }
const GURL& filesystem_url() const { return filesystem_url_; } const GURL& filesystem_url() const { return filesystem_url_; }
const std::string& blob_uuid() const { return blob_uuid_; } const std::string& blob_uuid() const { return blob_uuid_; }
const mojo::DataPipeConsumerHandle& data_pipe() const { const mojo::DataPipeConsumerHandle& data_pipe() const {
...@@ -137,6 +149,16 @@ class STORAGE_COMMON_EXPORT DataElement { ...@@ -137,6 +149,16 @@ class STORAGE_COMMON_EXPORT DataElement {
uint64_t length, uint64_t length,
const base::Time& expected_modification_time); const base::Time& expected_modification_time);
// Sets TYPE_RAW_FILE data with range. |file| must be open for asynchronous
// reading on Windows. It's recommended it also be opened with
// File::FLAG_DELETE_ON_CLOSE, since there's often no way to wait on the
// consumer to close the file.
void SetToFileRange(base::File file,
const base::FilePath& path,
uint64_t offset,
uint64_t length,
const base::Time& expected_modification_time);
// Sets TYPE_BLOB data with range. // Sets TYPE_BLOB data with range.
void SetToBlobRange(const std::string& blob_uuid, void SetToBlobRange(const std::string& blob_uuid,
uint64_t offset, uint64_t offset,
...@@ -155,6 +177,10 @@ class STORAGE_COMMON_EXPORT DataElement { ...@@ -155,6 +177,10 @@ class STORAGE_COMMON_EXPORT DataElement {
void SetToDataPipe(mojo::ScopedDataPipeConsumerHandle handle, void SetToDataPipe(mojo::ScopedDataPipeConsumerHandle handle,
blink::mojom::SizeGetterPtr size_getter); blink::mojom::SizeGetterPtr size_getter);
// Takes ownership of the File, if this is of TYPE_RAW_FILE. The file is open
// for reading (asynchronous reading on Windows).
base::File ReleaseFile();
mojo::ScopedDataPipeConsumerHandle ReleaseDataPipe( mojo::ScopedDataPipeConsumerHandle ReleaseDataPipe(
blink::mojom::SizeGetterPtr* size_getter); blink::mojom::SizeGetterPtr* size_getter);
...@@ -165,7 +191,8 @@ class STORAGE_COMMON_EXPORT DataElement { ...@@ -165,7 +191,8 @@ class STORAGE_COMMON_EXPORT DataElement {
Type type_; Type type_;
std::vector<char> buf_; // For TYPE_BYTES. std::vector<char> buf_; // For TYPE_BYTES.
const char* bytes_; // For TYPE_BYTES. const char* bytes_; // For TYPE_BYTES.
base::FilePath path_; // For TYPE_FILE. base::FilePath path_; // For TYPE_FILE and TYPE_RAW_FILE.
base::File file_; // For TYPE_RAW_FILE.
GURL filesystem_url_; // For TYPE_FILE_FILESYSTEM. GURL filesystem_url_; // For TYPE_FILE_FILESYSTEM.
std::string blob_uuid_; std::string blob_uuid_;
mojo::ScopedDataPipeConsumerHandle data_pipe_; mojo::ScopedDataPipeConsumerHandle data_pipe_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment