summaryrefslogtreecommitdiff
path: root/chromium/storage/browser/blob
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/storage/browser/blob')
-rw-r--r--chromium/storage/browser/blob/blob_async_builder_host.cc276
-rw-r--r--chromium/storage/browser/blob/blob_async_builder_host.h132
-rw-r--r--chromium/storage/browser/blob/blob_async_transport_strategy.cc337
-rw-r--r--chromium/storage/browser/blob/blob_async_transport_strategy.h126
-rw-r--r--chromium/storage/browser/blob/blob_data_builder.cc151
-rw-r--r--chromium/storage/browser/blob/blob_data_builder.h58
-rw-r--r--chromium/storage/browser/blob/blob_data_handle.cc15
-rw-r--r--chromium/storage/browser/blob/blob_data_handle.h1
-rw-r--r--chromium/storage/browser/blob/blob_data_item.cc35
-rw-r--r--chromium/storage/browser/blob/blob_data_item.h27
-rw-r--r--chromium/storage/browser/blob/blob_data_snapshot.cc5
-rw-r--r--chromium/storage/browser/blob/blob_data_snapshot.h2
-rw-r--r--chromium/storage/browser/blob/blob_reader.cc32
-rw-r--r--chromium/storage/browser/blob/blob_reader.h1
-rw-r--r--chromium/storage/browser/blob/blob_storage_context.cc67
-rw-r--r--chromium/storage/browser/blob/blob_storage_context.h9
-rw-r--r--chromium/storage/browser/blob/blob_storage_registry.cc118
-rw-r--r--chromium/storage/browser/blob/blob_storage_registry.h110
-rw-r--r--chromium/storage/browser/blob/blob_url_request_job.cc45
-rw-r--r--chromium/storage/browser/blob/blob_url_request_job.h5
-rw-r--r--chromium/storage/browser/blob/blob_url_request_job_factory.cc9
-rw-r--r--chromium/storage/browser/blob/blob_url_request_job_factory.h1
-rw-r--r--chromium/storage/browser/blob/internal_blob_data.cc5
-rw-r--r--chromium/storage/browser/blob/internal_blob_data.h3
-rw-r--r--chromium/storage/browser/blob/scoped_file.cc4
-rw-r--r--chromium/storage/browser/blob/scoped_file.h11
-rw-r--r--chromium/storage/browser/blob/shareable_file_reference.cc6
-rw-r--r--chromium/storage/browser/blob/shareable_file_reference.h1
-rw-r--r--chromium/storage/browser/blob/upload_blob_element_reader.cc5
-rw-r--r--chromium/storage/browser/blob/upload_blob_element_reader.h2
-rw-r--r--chromium/storage/browser/blob/view_blob_internals_job.cc12
-rw-r--r--chromium/storage/browser/blob/view_blob_internals_job.h1
32 files changed, 1471 insertions, 141 deletions
diff --git a/chromium/storage/browser/blob/blob_async_builder_host.cc b/chromium/storage/browser/blob/blob_async_builder_host.cc
new file mode 100644
index 00000000000..6d4432748c3
--- /dev/null
+++ b/chromium/storage/browser/blob/blob_async_builder_host.cc
@@ -0,0 +1,276 @@
+// Copyright 2015 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 "storage/browser/blob/blob_async_builder_host.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <utility>
+
+#include "base/memory/shared_memory.h"
+
+namespace storage {
+
+using MemoryItemRequest = BlobAsyncTransportStrategy::RendererMemoryItemRequest;
+
+BlobAsyncBuilderHost::BlobBuildingState::BlobBuildingState()
+ : next_request(0),
+ num_fulfilled_requests(0),
+ num_shared_memory_requests(0),
+ current_shared_memory_handle_index(0) {}
+
+BlobAsyncBuilderHost::BlobBuildingState::~BlobBuildingState() {}
+
+BlobAsyncBuilderHost::BlobAsyncBuilderHost() {}
+
+BlobAsyncBuilderHost::~BlobAsyncBuilderHost() {}
+
+bool BlobAsyncBuilderHost::StartBuildingBlob(
+ const std::string& uuid,
+ const std::string& type,
+ const std::vector<DataElement>& descriptions,
+ size_t memory_available,
+ const base::Callback<void(const std::vector<storage::BlobItemBytesRequest>&,
+ const std::vector<base::SharedMemoryHandle>&,
+ const std::vector<uint64_t>&)>& request_memory,
+ const base::Callback<void(const BlobDataBuilder&)>& done,
+ const base::Callback<void(IPCBlobCreationCancelCode)>& cancel) {
+ if (async_blob_map_.find(uuid) != async_blob_map_.end())
+ return false;
+ if (BlobAsyncTransportStrategy::ShouldBeShortcut(descriptions,
+ memory_available)) {
+ // We have enough memory, and all the data is here, so we use the shortcut
+ // method and populate the old way.
+ BlobDataBuilder builder(uuid);
+ builder.set_content_type(type);
+ for (const DataElement& element : descriptions) {
+ builder.AppendIPCDataElement(element);
+ }
+ done.Run(builder);
+ return true;
+ }
+
+ scoped_ptr<BlobBuildingState> state(new BlobBuildingState());
+ BlobBuildingState* state_ptr = state.get();
+ async_blob_map_[uuid] = std::move(state);
+ state_ptr->type = type;
+ state_ptr->request_memory_callback = request_memory;
+ state_ptr->done_callback = done;
+ state_ptr->cancel_callback = cancel;
+
+ // We are currently only operating in 'no disk' mode. This will change in
+ // future patches to enable disk storage.
+ // Since we don't have a disk yet, we put 0 for disk_space_left.
+ state_ptr->transport_strategy.Initialize(
+ max_ipc_memory_size_, max_shared_memory_size_, max_file_size_,
+ 0 /* disk_space_left */, memory_available, uuid, descriptions);
+
+ switch (state_ptr->transport_strategy.error()) {
+ case BlobAsyncTransportStrategy::ERROR_TOO_LARGE:
+ // Cancel cleanly, we're out of memory.
+ CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
+ return true;
+ case BlobAsyncTransportStrategy::ERROR_INVALID_PARAMS:
+ // Bad IPC, so we ignore and clean up.
+ VLOG(1) << "Error initializing transport strategy: "
+ << state_ptr->transport_strategy.error();
+ async_blob_map_.erase(async_blob_map_.find(uuid));
+ return false;
+ case BlobAsyncTransportStrategy::ERROR_NONE:
+ ContinueBlobMemoryRequests(uuid);
+ return true;
+ }
+ return false;
+}
+
+bool BlobAsyncBuilderHost::OnMemoryResponses(
+ const std::string& uuid,
+ const std::vector<BlobItemBytesResponse>& responses) {
+ if (responses.empty()) {
+ return false;
+ }
+ AsyncBlobMap::const_iterator state_it = async_blob_map_.find(uuid);
+ if (state_it == async_blob_map_.end()) {
+ // There's a possibility that we had a shared memory error, and there were
+ // still responses in flight. So we don't fail here, we just ignore.
+ DVLOG(1) << "Could not find blob " << uuid;
+ return true;
+ }
+ BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second.get();
+ BlobAsyncTransportStrategy& strategy = state->transport_strategy;
+ bool invalid_ipc = false;
+ bool memory_error = false;
+ const auto& requests = strategy.requests();
+ for (const BlobItemBytesResponse& response : responses) {
+ if (response.request_number >= requests.size()) {
+ // Bad IPC, so we delete our record and ignore.
+ DVLOG(1) << "Invalid request number " << response.request_number;
+ async_blob_map_.erase(state_it);
+ return false;
+ }
+ const MemoryItemRequest& request = requests[response.request_number];
+ if (request.received) {
+ // Bad IPC, so we delete our record.
+ DVLOG(1) << "Already received response for that request.";
+ async_blob_map_.erase(state_it);
+ return false;
+ }
+ strategy.MarkRequestAsReceived(response.request_number);
+ switch (request.message.transport_strategy) {
+ case IPCBlobItemRequestStrategy::IPC:
+ if (response.inline_data.size() < request.message.size) {
+ DVLOG(1) << "Invalid data size " << response.inline_data.size()
+ << " vs requested size of " << request.message.size;
+ invalid_ipc = true;
+ break;
+ }
+ invalid_ipc = !strategy.blob_builder()->PopulateFutureData(
+ request.browser_item_index, &response.inline_data[0],
+ request.browser_item_offset, request.message.size);
+ break;
+ case IPCBlobItemRequestStrategy::SHARED_MEMORY:
+ if (state->num_shared_memory_requests == 0) {
+ DVLOG(1) << "Received too many responses for shared memory.";
+ invalid_ipc = true;
+ break;
+ }
+ state->num_shared_memory_requests--;
+ if (!state->shared_memory_block->memory()) {
+ // We just map the whole block, as we'll probably be accessing the
+ // whole thing in this group of responses. Another option is to use
+ // MapAt, remove the mapped boolean, and then exclude the
+ // handle_offset below.
+ size_t handle_size = strategy.handle_sizes().at(
+ state->current_shared_memory_handle_index);
+ if (!state->shared_memory_block->Map(handle_size)) {
+ DVLOG(1) << "Unable to map memory to size " << handle_size;
+ memory_error = true;
+ break;
+ }
+ }
+
+ invalid_ipc = !strategy.blob_builder()->PopulateFutureData(
+ request.browser_item_index,
+ static_cast<const char*>(state->shared_memory_block->memory()) +
+ request.message.handle_offset,
+ request.browser_item_offset, request.message.size);
+ break;
+ case IPCBlobItemRequestStrategy::FILE:
+ case IPCBlobItemRequestStrategy::UNKNOWN:
+ DVLOG(1) << "Not implemented.";
+ invalid_ipc = true;
+ break;
+ }
+ if (invalid_ipc) {
+ // Bad IPC, so we delete our record and return false.
+ async_blob_map_.erase(state_it);
+ return false;
+ }
+ if (memory_error) {
+ DVLOG(1) << "Shared memory error.";
+ CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
+ return true;
+ }
+ state->num_fulfilled_requests++;
+ }
+ ContinueBlobMemoryRequests(uuid);
+ return true;
+}
+
+void BlobAsyncBuilderHost::StopBuildingBlob(const std::string& uuid) {
+ async_blob_map_.erase(async_blob_map_.find(uuid));
+}
+
+void BlobAsyncBuilderHost::ContinueBlobMemoryRequests(const std::string& uuid) {
+ AsyncBlobMap::const_iterator state_it = async_blob_map_.find(uuid);
+ DCHECK(state_it != async_blob_map_.end());
+ BlobAsyncBuilderHost::BlobBuildingState* state = state_it->second.get();
+
+ const std::vector<MemoryItemRequest>& requests =
+ state->transport_strategy.requests();
+ BlobAsyncTransportStrategy& strategy = state->transport_strategy;
+ size_t num_requests = requests.size();
+ if (state->num_fulfilled_requests == num_requests) {
+ DoneAndCleanup(uuid);
+ return;
+ }
+ DCHECK_LT(state->num_fulfilled_requests, num_requests);
+ if (state->next_request == num_requests) {
+ // We are still waiting on other requests to come back.
+ return;
+ }
+
+ std::vector<BlobItemBytesRequest> byte_requests;
+ std::vector<base::SharedMemoryHandle> shared_memory;
+ std::vector<uint64_t> files;
+
+ for (; state->next_request < num_requests; ++state->next_request) {
+ const MemoryItemRequest& request = requests[state->next_request];
+
+ bool stop_accumulating = false;
+ bool using_shared_memory_handle = state->num_shared_memory_requests > 0;
+ switch (request.message.transport_strategy) {
+ case IPCBlobItemRequestStrategy::IPC:
+ byte_requests.push_back(request.message);
+ break;
+ case IPCBlobItemRequestStrategy::SHARED_MEMORY:
+ if (using_shared_memory_handle &&
+ state->current_shared_memory_handle_index !=
+ request.message.handle_index) {
+ // We only want one shared memory per requesting blob.
+ stop_accumulating = true;
+ break;
+ }
+ using_shared_memory_handle = true;
+ state->current_shared_memory_handle_index =
+ request.message.handle_index;
+ state->num_shared_memory_requests++;
+
+ if (!state->shared_memory_block) {
+ state->shared_memory_block.reset(new base::SharedMemory());
+ size_t size = strategy.handle_sizes()[request.message.handle_index];
+ if (!state->shared_memory_block->CreateAnonymous(size)) {
+ DVLOG(1) << "Unable to allocate shared memory for blob transfer.";
+ CancelAndCleanup(uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
+ return;
+ }
+ }
+ shared_memory.push_back(state->shared_memory_block->handle());
+ byte_requests.push_back(request.message);
+ // Since we are only using one handle at a time, transform our handle
+ // index correctly back to 0.
+ byte_requests.back().handle_index = 0;
+ break;
+ case IPCBlobItemRequestStrategy::FILE:
+ case IPCBlobItemRequestStrategy::UNKNOWN:
+ NOTREACHED() << "Not implemented yet.";
+ break;
+ }
+ if (stop_accumulating) {
+ break;
+ }
+ }
+
+ DCHECK(!requests.empty());
+
+ state->request_memory_callback.Run(byte_requests, shared_memory, files);
+}
+
+void BlobAsyncBuilderHost::CancelAndCleanup(const std::string& uuid,
+ IPCBlobCreationCancelCode code) {
+ scoped_ptr<BlobBuildingState> state = std::move(async_blob_map_[uuid]);
+ async_blob_map_.erase(uuid);
+ state->cancel_callback.Run(code);
+}
+
+void BlobAsyncBuilderHost::DoneAndCleanup(const std::string& uuid) {
+ scoped_ptr<BlobBuildingState> state = std::move(async_blob_map_[uuid]);
+ async_blob_map_.erase(uuid);
+ BlobDataBuilder* builder = state->transport_strategy.blob_builder();
+ builder->set_content_type(state->type);
+ state->done_callback.Run(*builder);
+}
+
+} // namespace storage
diff --git a/chromium/storage/browser/blob/blob_async_builder_host.h b/chromium/storage/browser/blob/blob_async_builder_host.h
new file mode 100644
index 00000000000..c84f2b5d348
--- /dev/null
+++ b/chromium/storage/browser/blob/blob_async_builder_host.h
@@ -0,0 +1,132 @@
+// Copyright 2015 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 STORAGE_BROWSER_BLOB_BLOB_ASYNC_BUILDER_HOST_H_
+#define STORAGE_BROWSER_BLOB_BLOB_ASYNC_BUILDER_HOST_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory_handle.h"
+#include "storage/browser/blob/blob_async_transport_strategy.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/storage_browser_export.h"
+#include "storage/common/blob_storage/blob_item_bytes_request.h"
+#include "storage/common/blob_storage/blob_item_bytes_response.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
+#include "storage/common/data_element.h"
+
+namespace base {
+class SharedMemory;
+}
+
+namespace storage {
+
+// This class holds all blobs that are currently being built asynchronously for
+// a child process. It sends memory request, cancel, and done messages through
+// the given callbacks.
+// This also includes handling 'shortcut' logic, where the host will use the
+// initial data in the description instead of requesting for data if we have
+// enough immediate space.
+class STORAGE_EXPORT BlobAsyncBuilderHost {
+ public:
+ BlobAsyncBuilderHost();
+ virtual ~BlobAsyncBuilderHost();
+
+ // This method begins the construction of the blob given the descriptions.
+ // After this method is called, either of the following can happen.
+ // * The |done| callback is triggered immediately because we can shortcut the
+ // construction.
+ // * The |request_memory| callback is called to request memory from the
+ // renderer. This class waits for calls to OnMemoryResponses to continue.
+ // The last argument in the callback corresponds to file handle sizes.
+ // When all memory is recieved, the |done| callback is triggered.
+ // * The |cancel| callback is triggered if there is an error at any point. All
+ // state for the cancelled blob is cleared before |cancel| is called.
+ // Returns if the arguments are valid and we have a good IPC message.
+ bool StartBuildingBlob(
+ const std::string& uuid,
+ const std::string& type,
+ const std::vector<DataElement>& descriptions,
+ size_t memory_available,
+ const base::Callback<
+ void(const std::vector<storage::BlobItemBytesRequest>&,
+ const std::vector<base::SharedMemoryHandle>&,
+ const std::vector<uint64_t>&)>& request_memory,
+ const base::Callback<void(const BlobDataBuilder&)>& done,
+ const base::Callback<void(IPCBlobCreationCancelCode)>& cancel);
+
+ // This is called when we have responses from the Renderer to our calls to
+ // the request_memory callback above.
+ // Returns if the arguments are valid and we have a good IPC message.
+ bool OnMemoryResponses(const std::string& uuid,
+ const std::vector<BlobItemBytesResponse>& responses);
+
+ // This erases the blob building state.
+ void StopBuildingBlob(const std::string& uuid);
+
+ size_t blob_building_count() const { return async_blob_map_.size(); }
+
+ // For testing use only. Must be called before StartBuildingBlob.
+ void SetMemoryConstantsForTesting(size_t max_ipc_memory_size,
+ size_t max_shared_memory_size,
+ uint64_t max_file_size) {
+ max_ipc_memory_size_ = max_ipc_memory_size;
+ max_shared_memory_size_ = max_shared_memory_size;
+ max_file_size_ = max_file_size;
+ }
+
+ private:
+ struct BlobBuildingState {
+ BlobBuildingState();
+ ~BlobBuildingState();
+
+ std::string type;
+ BlobAsyncTransportStrategy transport_strategy;
+ size_t next_request;
+ size_t num_fulfilled_requests;
+ scoped_ptr<base::SharedMemory> shared_memory_block;
+ // This is the number of requests that have been sent to populate the above
+ // shared data. We won't ask for more data in shared memory until all
+ // requests have been responded to.
+ size_t num_shared_memory_requests;
+ // Only relevant if num_shared_memory_requests is > 0
+ size_t current_shared_memory_handle_index;
+
+ base::Callback<void(const std::vector<storage::BlobItemBytesRequest>&,
+ const std::vector<base::SharedMemoryHandle>&,
+ const std::vector<uint64_t>&)> request_memory_callback;
+ base::Callback<void(const BlobDataBuilder&)> done_callback;
+ base::Callback<void(IPCBlobCreationCancelCode)> cancel_callback;
+ };
+
+ typedef std::map<std::string, scoped_ptr<BlobBuildingState>> AsyncBlobMap;
+
+ // This is the 'main loop' of our memory requests to the renderer.
+ void ContinueBlobMemoryRequests(const std::string& uuid);
+
+ void CancelAndCleanup(const std::string& uuid,
+ IPCBlobCreationCancelCode code);
+ void DoneAndCleanup(const std::string& uuid);
+
+ AsyncBlobMap async_blob_map_;
+
+ // Here for testing.
+ size_t max_ipc_memory_size_ = kBlobStorageIPCThresholdBytes;
+ size_t max_shared_memory_size_ = kBlobStorageMaxSharedMemoryBytes;
+ uint64_t max_file_size_ = kBlobStorageMaxFileSizeBytes;
+
+ DISALLOW_COPY_AND_ASSIGN(BlobAsyncBuilderHost);
+};
+
+} // namespace storage
+#endif // STORAGE_BROWSER_BLOB_BLOB_ASYNC_BUILDER_HOST_H_
diff --git a/chromium/storage/browser/blob/blob_async_transport_strategy.cc b/chromium/storage/browser/blob/blob_async_transport_strategy.cc
new file mode 100644
index 00000000000..edae52c79ed
--- /dev/null
+++ b/chromium/storage/browser/blob/blob_async_transport_strategy.cc
@@ -0,0 +1,337 @@
+// Copyright 2015 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 <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "base/numerics/safe_math.h"
+#include "storage/browser/blob/blob_async_transport_strategy.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
+
+namespace storage {
+namespace {
+bool IsBytes(DataElement::Type type) {
+ return type == DataElement::TYPE_BYTES ||
+ type == DataElement::TYPE_BYTES_DESCRIPTION;
+}
+
+// This is the general template that each strategy below implements. See the
+// ForEachWithSegment method for a description of how these are called.
+// class BlobSegmentVisitor {
+// public:
+// typedef ___ SizeType;
+// void VisitBytesSegment(size_t element_index, uint64_t element_offset,
+// size_t segment_index, uint64_t segment_offset,
+// uint64_t size);
+// void VisitNonBytesSegment(const DataElement& element, size_t element_idx);
+// void Done();
+// };
+
+// This class handles the logic of how transported memory is going to be
+// represented as storage in the browser. The main idea is that all the memory
+// is now packed into file chunks, and the browser items will just reference
+// the file with offsets and sizes.
+class FileStorageStrategy {
+ public:
+ FileStorageStrategy(
+ std::vector<BlobAsyncTransportStrategy::RendererMemoryItemRequest>*
+ requests,
+ BlobDataBuilder* builder)
+ : requests(requests), builder(builder), current_item_index(0) {}
+
+ ~FileStorageStrategy() {}
+
+ void VisitBytesSegment(size_t element_index,
+ uint64_t element_offset,
+ size_t segment_index,
+ uint64_t segment_offset,
+ uint64_t size) {
+ BlobAsyncTransportStrategy::RendererMemoryItemRequest request;
+ request.browser_item_index = current_item_index;
+ request.browser_item_offset = 0;
+ request.message.request_number = requests->size();
+ request.message.transport_strategy = IPCBlobItemRequestStrategy::FILE;
+ request.message.renderer_item_index = element_index;
+ request.message.renderer_item_offset = element_offset;
+ request.message.size = size;
+ request.message.handle_index = segment_index;
+ request.message.handle_offset = segment_offset;
+
+ requests->push_back(request);
+ builder->AppendFutureFile(segment_offset, size);
+ current_item_index++;
+ }
+
+ void VisitNonBytesSegment(const DataElement& element, size_t element_index) {
+ builder->AppendIPCDataElement(element);
+ current_item_index++;
+ }
+
+ void Done() {}
+
+ std::vector<BlobAsyncTransportStrategy::RendererMemoryItemRequest>* requests;
+ BlobDataBuilder* builder;
+
+ size_t current_item_index;
+};
+
+// This class handles the logic of storing memory that is transported as
+// consolidated shared memory.
+class SharedMemoryStorageStrategy {
+ public:
+ SharedMemoryStorageStrategy(
+ size_t max_segment_size,
+ std::vector<BlobAsyncTransportStrategy::RendererMemoryItemRequest>*
+ requests,
+ BlobDataBuilder* builder)
+ : requests(requests),
+ max_segment_size(max_segment_size),
+ builder(builder),
+ current_item_size(0),
+ current_item_index(0) {}
+ ~SharedMemoryStorageStrategy() {}
+
+ void VisitBytesSegment(size_t element_index,
+ uint64_t element_offset,
+ size_t segment_index,
+ uint64_t segment_offset,
+ uint64_t size) {
+ if (current_item_size + size > max_segment_size) {
+ builder->AppendFutureData(current_item_size);
+ current_item_index++;
+ current_item_size = 0;
+ }
+ BlobAsyncTransportStrategy::RendererMemoryItemRequest request;
+ request.browser_item_index = current_item_index;
+ request.browser_item_offset = current_item_size;
+ request.message.request_number = requests->size();
+ request.message.transport_strategy =
+ IPCBlobItemRequestStrategy::SHARED_MEMORY;
+ request.message.renderer_item_index = element_index;
+ request.message.renderer_item_offset = element_offset;
+ request.message.size = size;
+ request.message.handle_index = segment_index;
+ request.message.handle_offset = segment_offset;
+
+ requests->push_back(request);
+ current_item_size += size;
+ }
+
+ void VisitNonBytesSegment(const DataElement& element, size_t element_index) {
+ if (current_item_size != 0) {
+ builder->AppendFutureData(current_item_size);
+ current_item_index++;
+ }
+ builder->AppendIPCDataElement(element);
+ current_item_index++;
+ current_item_size = 0;
+ }
+
+ void Done() {
+ if (current_item_size != 0) {
+ builder->AppendFutureData(current_item_size);
+ }
+ }
+
+ std::vector<BlobAsyncTransportStrategy::RendererMemoryItemRequest>* requests;
+
+ size_t max_segment_size;
+ BlobDataBuilder* builder;
+ size_t current_item_size;
+ uint64_t current_item_index;
+};
+
+// This iterates of the data elements and segments the 'bytes' data into
+// the smallest number of segments given the max_segment_size.
+// The callback describes either:
+// * A non-memory item
+// * A partition of a bytes element which will be populated into a given
+// segment and segment offset.
+// More specifically, we split each |element| into one or more |segments| of a
+// max_size, invokes the strategy to determine the request to make for each
+// |segment| produced. A |segment| can also span multiple |elements|.
+// Assumptions: All memory items are consolidated. As in, there are no two
+// 'bytes' items next to eachother.
+template <typename Visitor>
+void ForEachWithSegment(const std::vector<DataElement>& elements,
+ uint64_t max_segment_size,
+ Visitor* visitor) {
+ DCHECK_GT(max_segment_size, 0ull);
+ size_t segment_index = 0;
+ uint64_t segment_offset = 0;
+ size_t elements_length = elements.size();
+ for (size_t element_index = 0; element_index < elements_length;
+ ++element_index) {
+ const auto& element = elements.at(element_index);
+ DataElement::Type type = element.type();
+ if (!IsBytes(type)) {
+ visitor->VisitNonBytesSegment(element, element_index);
+ continue;
+ }
+ uint64_t element_memory_left = element.length();
+ uint64_t element_offset = 0;
+ while (element_memory_left > 0) {
+ if (segment_offset == max_segment_size) {
+ ++segment_index;
+ segment_offset = 0;
+ }
+ uint64_t memory_writing =
+ std::min(max_segment_size - segment_offset, element_memory_left);
+ visitor->VisitBytesSegment(element_index, element_offset, segment_index,
+ segment_offset, memory_writing);
+ element_memory_left -= memory_writing;
+ segment_offset += memory_writing;
+ element_offset += memory_writing;
+ }
+ }
+ visitor->Done();
+}
+} // namespace
+
+BlobAsyncTransportStrategy::RendererMemoryItemRequest::
+ RendererMemoryItemRequest()
+ : browser_item_index(0), browser_item_offset(0), received(false) {}
+
+BlobAsyncTransportStrategy::BlobAsyncTransportStrategy()
+ : error_(BlobAsyncTransportStrategy::ERROR_NONE), total_bytes_size_(0) {}
+
+BlobAsyncTransportStrategy::~BlobAsyncTransportStrategy() {}
+
+// if total_blob_size > |memory_available| (say 400MB)
+// Request all data in files
+// (Segment all of the existing data into
+// file blocks, of <= |max_file_size|)
+// else if total_blob_size > |max_ipc_memory_size| (say 150KB)
+// Request all data in shared memory
+// (Segment all of the existing data into
+// shared memory blocks, of <= |max_shared_memory_size|)
+// else
+// Request all data to be sent over IPC
+void BlobAsyncTransportStrategy::Initialize(
+ size_t max_ipc_memory_size,
+ size_t max_shared_memory_size,
+ size_t max_file_size,
+ uint64_t disk_space_left,
+ size_t memory_available,
+ const std::string& uuid,
+ const std::vector<DataElement>& blob_item_infos) {
+ DCHECK(handle_sizes_.empty());
+ DCHECK(requests_.empty());
+ DCHECK(!builder_.get());
+ builder_.reset(new BlobDataBuilder(uuid));
+ error_ = BlobAsyncTransportStrategy::ERROR_NONE;
+
+ size_t memory_items = 0;
+ base::CheckedNumeric<uint64_t> total_size_checked = 0;
+ for (const auto& info : blob_item_infos) {
+ if (!IsBytes(info.type())) {
+ continue;
+ }
+ total_size_checked += info.length();
+ ++memory_items;
+ }
+
+ if (!total_size_checked.IsValid()) {
+ DVLOG(1) << "Impossible total size of all memory elements.";
+ error_ = BlobAsyncTransportStrategy::ERROR_INVALID_PARAMS;
+ return;
+ }
+
+ total_bytes_size_ = total_size_checked.ValueOrDie();
+
+ // See if we have enough memory.
+ if (total_bytes_size_ >
+ disk_space_left + static_cast<uint64_t>(memory_available)) {
+ error_ = BlobAsyncTransportStrategy::ERROR_TOO_LARGE;
+ return;
+ }
+
+ // If we're more than the available memory, then we're going straight to disk.
+ if (total_bytes_size_ > memory_available) {
+ if (total_bytes_size_ > disk_space_left) {
+ error_ = BlobAsyncTransportStrategy::ERROR_TOO_LARGE;
+ return;
+ }
+ ComputeHandleSizes(total_bytes_size_, max_file_size, &handle_sizes_);
+ FileStorageStrategy strategy(&requests_, builder_.get());
+ ForEachWithSegment(blob_item_infos, static_cast<uint64_t>(max_file_size),
+ &strategy);
+ return;
+ }
+
+ if (total_bytes_size_ > max_ipc_memory_size) {
+ // Note: The size must be <= std::numeric_limits<size_t>::max(). Otherwise
+ // we are guarenteed to be caught by the if statement above,
+ // |total_bytes_size_ > memory_available|.
+ ComputeHandleSizes(total_bytes_size_, max_shared_memory_size,
+ &handle_sizes_);
+ SharedMemoryStorageStrategy strategy(max_shared_memory_size, &requests_,
+ builder_.get());
+ ForEachWithSegment(blob_item_infos,
+ static_cast<uint64_t>(max_shared_memory_size),
+ &strategy);
+ return;
+ }
+
+ // Since they can all fit in IPC memory, we don't need to segment anything,
+ // and just request them straight in IPC.
+ size_t items_length = blob_item_infos.size();
+ for (size_t i = 0; i < items_length; i++) {
+ const auto& info = blob_item_infos.at(i);
+ if (!IsBytes(info.type())) {
+ builder_->AppendIPCDataElement(info);
+ continue;
+ }
+ BlobAsyncTransportStrategy::RendererMemoryItemRequest request;
+ request.browser_item_index = i;
+ request.browser_item_offset = 0;
+ request.message.request_number = requests_.size();
+ request.message.transport_strategy = IPCBlobItemRequestStrategy::IPC;
+ request.message.renderer_item_index = i;
+ request.message.renderer_item_offset = 0;
+ request.message.size = info.length();
+ requests_.push_back(request);
+ builder_->AppendFutureData(info.length());
+ }
+}
+
+/* static */
+bool BlobAsyncTransportStrategy::ShouldBeShortcut(
+ const std::vector<DataElement>& elements,
+ size_t memory_available) {
+ base::CheckedNumeric<size_t> shortcut_bytes = 0;
+ for (const auto& element : elements) {
+ DataElement::Type type = element.type();
+ if (type == DataElement::TYPE_BYTES_DESCRIPTION) {
+ return false;
+ }
+ if (type == DataElement::TYPE_BYTES) {
+ shortcut_bytes += element.length();
+ if (!shortcut_bytes.IsValid()) {
+ return false;
+ }
+ }
+ }
+ return shortcut_bytes.ValueOrDie() <= memory_available;
+}
+
+/* static */
+void BlobAsyncTransportStrategy::ComputeHandleSizes(
+ uint64_t total_memory_size,
+ size_t max_segment_size,
+ std::vector<size_t>* segment_sizes) {
+ size_t total_max_segments =
+ static_cast<size_t>(total_memory_size / max_segment_size);
+ bool has_extra_segment = (total_memory_size % max_segment_size) > 0;
+ segment_sizes->reserve(total_max_segments + (has_extra_segment ? 1 : 0));
+ segment_sizes->insert(segment_sizes->begin(), total_max_segments,
+ max_segment_size);
+ if (has_extra_segment) {
+ segment_sizes->push_back(total_memory_size % max_segment_size);
+ }
+}
+
+} // namespace storage
diff --git a/chromium/storage/browser/blob/blob_async_transport_strategy.h b/chromium/storage/browser/blob/blob_async_transport_strategy.h
new file mode 100644
index 00000000000..3e0777182cb
--- /dev/null
+++ b/chromium/storage/browser/blob/blob_async_transport_strategy.h
@@ -0,0 +1,126 @@
+// Copyright 2015 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 STORAGE_BROWSER_BLOB_BLOB_ASYNC_TRANSPORT_STRATEGY_H_
+#define STORAGE_BROWSER_BLOB_BLOB_ASYNC_TRANSPORT_STRATEGY_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <map>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/storage_browser_export.h"
+#include "storage/common/blob_storage/blob_item_bytes_request.h"
+#include "storage/common/data_element.h"
+
+namespace storage {
+
+// This class computes and stores the strategy for asynchronously transporting
+// memory from the renderer to the browser. We take memory constraints of our
+// system and the description of a blob, and figure out:
+// 1) How to store the blob data in the browser process: in memory or on disk.
+// 2) How to transport the data from the renderer: ipc payload, shared memory,
+// or file handles.
+// We then generate data requests for that blob's memory and seed a
+// BlobDataBuilder for storing that data.
+//
+// Note: This class does not compute requests by using the 'shortcut' method,
+// where the data is already present in the blob description, and will
+// always give the caller the full strategy for requesting all data from
+// the renderer.
+class STORAGE_EXPORT BlobAsyncTransportStrategy {
+ public:
+ enum Error {
+ ERROR_NONE = 0,
+ ERROR_TOO_LARGE, // This item can't fit in disk or memory
+ ERROR_INVALID_PARAMS
+ };
+
+ struct RendererMemoryItemRequest {
+ RendererMemoryItemRequest();
+ // This is the index of the item in the builder on the browser side.
+ size_t browser_item_index;
+ // Note: For files this offset should always be 0, as the file offset in
+ // segmentation is handled by the handle_offset in the message. This
+ // offset is used for populating a chunk when the data comes back to
+ // the browser.
+ size_t browser_item_offset;
+ BlobItemBytesRequest message;
+ bool received;
+ };
+
+ BlobAsyncTransportStrategy();
+ virtual ~BlobAsyncTransportStrategy();
+
+ // This call does the computation to create the requests and builder for the
+ // blob given the memory constraints and blob description. |memory_available|
+ // is the total amount of memory we can offer for storing blobs.
+ // This method can only be called once.
+ void Initialize(size_t max_ipc_memory_size,
+ size_t max_shared_memory_size,
+ size_t max_file_size,
+ uint64_t disk_space_left,
+ size_t memory_available,
+ const std::string& uuid,
+ const std::vector<DataElement>& blob_item_infos);
+
+ // The sizes of the handles being used (by handle index) in the async
+ // operation. This is used for both files or shared memory, as their use is
+ // mutually exclusive.
+ const std::vector<size_t>& handle_sizes() const { return handle_sizes_; }
+
+ // The requests for memory, segmented as described above, along with their
+ // destination browser indexes and offsets.
+ const std::vector<RendererMemoryItemRequest>& requests() const {
+ return requests_;
+ }
+
+ // Marks the request at the given request number as recieved.
+ void MarkRequestAsReceived(size_t request_num) {
+ DCHECK_LT(request_num, requests_.size());
+ requests_[request_num].received = true;
+ }
+
+ // A BlobDataBuilder which can be used to construct the Blob in the
+ // BlobStorageContext object after:
+ // * The bytes items from AppendFutureData are populated by
+ // PopulateFutureData.
+ // * The temporary files from AppendFutureFile are populated by
+ // PopulateFutureFile.
+ BlobDataBuilder* blob_builder() { return builder_.get(); }
+
+ // The total bytes size of memory items in the blob.
+ uint64_t total_bytes_size() const { return total_bytes_size_; }
+
+ Error error() const { return error_; }
+
+ static bool ShouldBeShortcut(const std::vector<DataElement>& items,
+ size_t memory_available);
+
+ private:
+ static void ComputeHandleSizes(uint64_t total_memory_size,
+ size_t max_segment_size,
+ std::vector<size_t>* segment_sizes);
+
+ Error error_;
+
+ // We use the same vector for shared memory handle sizes and file handle sizes
+ // because we only use one for any strategy. The size of the handles is capped
+ // by the |max_file_size| argument in Initialize, so we can just use size_t.
+ std::vector<size_t> handle_sizes_;
+
+ uint64_t total_bytes_size_;
+ std::vector<RendererMemoryItemRequest> requests_;
+ scoped_ptr<BlobDataBuilder> builder_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlobAsyncTransportStrategy);
+};
+
+} // namespace storage
+
+#endif // STORAGE_BROWSER_BLOB_BLOB_ASYNC_TRANSPORT_STRATEGY_H_
diff --git a/chromium/storage/browser/blob/blob_data_builder.cc b/chromium/storage/browser/blob/blob_data_builder.cc
index 94fb9e50388..b6999104b95 100644
--- a/chromium/storage/browser/blob/blob_data_builder.cc
+++ b/chromium/storage/browser/blob/blob_data_builder.cc
@@ -4,23 +4,136 @@
#include "storage/browser/blob/blob_data_builder.h"
+#include <stddef.h>
+#include <stdint.h>
+#include <utility>
+
+#include "base/numerics/safe_conversions.h"
+#include "base/numerics/safe_math.h"
#include "base/time/time.h"
#include "net/disk_cache/disk_cache.h"
#include "storage/browser/blob/shareable_file_reference.h"
namespace storage {
+const char BlobDataBuilder::kAppendFutureFileTemporaryFileName[] =
+ "kFakeFilenameToBeChangedByPopulateFutureFile";
+
BlobDataBuilder::BlobDataBuilder(const std::string& uuid) : uuid_(uuid) {
}
BlobDataBuilder::~BlobDataBuilder() {
}
+void BlobDataBuilder::AppendIPCDataElement(const DataElement& ipc_data) {
+ uint64_t length = ipc_data.length();
+ switch (ipc_data.type()) {
+ case DataElement::TYPE_BYTES:
+ DCHECK(!ipc_data.offset());
+ AppendData(ipc_data.bytes(),
+ base::checked_cast<size_t, uint64_t>(length));
+ break;
+ case DataElement::TYPE_FILE:
+ AppendFile(ipc_data.path(), ipc_data.offset(), length,
+ ipc_data.expected_modification_time());
+ break;
+ case DataElement::TYPE_FILE_FILESYSTEM:
+ AppendFileSystemFile(ipc_data.filesystem_url(), ipc_data.offset(), length,
+ ipc_data.expected_modification_time());
+ break;
+ case DataElement::TYPE_BLOB:
+ // This is a temporary item that will be deconstructed later in
+ // BlobStorageContext.
+ AppendBlob(ipc_data.blob_uuid(), ipc_data.offset(), ipc_data.length());
+ break;
+ case DataElement::TYPE_BYTES_DESCRIPTION:
+ case DataElement::TYPE_UNKNOWN:
+ case DataElement::TYPE_DISK_CACHE_ENTRY: // This type can't be sent by IPC.
+ NOTREACHED();
+ break;
+ }
+}
+
void BlobDataBuilder::AppendData(const char* data, size_t length) {
if (!length)
return;
scoped_ptr<DataElement> element(new DataElement());
element->SetToBytes(data, length);
- items_.push_back(new BlobDataItem(element.Pass()));
+ items_.push_back(new BlobDataItem(std::move(element)));
+}
+
+size_t BlobDataBuilder::AppendFutureData(size_t length) {
+ CHECK_NE(length, 0u);
+ scoped_ptr<DataElement> element(new DataElement());
+ element->SetToBytesDescription(length);
+ items_.push_back(new BlobDataItem(std::move(element)));
+ return items_.size() - 1;
+}
+
+bool BlobDataBuilder::PopulateFutureData(size_t index,
+ const char* data,
+ size_t offset,
+ size_t length) {
+ DCHECK_LT(index, items_.size());
+ DCHECK(data);
+ DataElement* element = items_.at(index)->data_element_ptr();
+
+ // We lazily allocate our data buffer by waiting until the first
+ // PopulateFutureData call.
+ // Why? The reason we have the AppendFutureData method is to create our Blob
+ // record when the Renderer tells us about the blob without actually
+ // allocating the memory yet, as we might not have the quota yet. So we don't
+ // want to allocate the memory until we're actually receiving the data (which
+ // the browser process only does when it has quota).
+ if (element->type() == DataElement::TYPE_BYTES_DESCRIPTION) {
+ element->SetToAllocatedBytes(element->length());
+ // The type of the element is now TYPE_BYTES.
+ }
+ if (element->type() != DataElement::TYPE_BYTES) {
+ DVLOG(1) << "Invalid item type.";
+ return false;
+ }
+ base::CheckedNumeric<size_t> checked_end = offset;
+ checked_end += length;
+ if (!checked_end.IsValid() || checked_end.ValueOrDie() > element->length()) {
+ DVLOG(1) << "Invalid offset or length.";
+ return false;
+ }
+ std::memcpy(element->mutable_bytes() + offset, data, length);
+ return true;
+}
+
+size_t BlobDataBuilder::AppendFutureFile(uint64_t offset, uint64_t length) {
+ CHECK_NE(length, 0ull);
+ scoped_ptr<DataElement> element(new DataElement());
+ element->SetToFilePathRange(base::FilePath::FromUTF8Unsafe(std::string(
+ kAppendFutureFileTemporaryFileName)),
+ offset, length, base::Time());
+ items_.push_back(new BlobDataItem(std::move(element)));
+ return items_.size() - 1;
+}
+
+bool BlobDataBuilder::PopulateFutureFile(
+ size_t index,
+ const scoped_refptr<ShareableFileReference>& file_reference,
+ const base::Time& expected_modification_time) {
+ DCHECK_LT(index, items_.size());
+ DataElement* old_element = items_.at(index)->data_element_ptr();
+
+ if (old_element->type() != DataElement::TYPE_FILE) {
+ DVLOG(1) << "Invalid item type.";
+ return false;
+ } else if (old_element->path().AsUTF8Unsafe() !=
+ std::string(kAppendFutureFileTemporaryFileName)) {
+ DVLOG(1) << "Item not created by AppendFutureFile";
+ return false;
+ }
+ uint64_t length = old_element->length();
+ uint64_t offset = old_element->offset();
+ scoped_ptr<DataElement> element(new DataElement());
+ element->SetToFilePathRange(file_reference->path(), offset, length,
+ expected_modification_time);
+ items_[index] = new BlobDataItem(std::move(element), file_reference);
+ return true;
}
void BlobDataBuilder::AppendFile(const base::FilePath& file_path,
@@ -30,8 +143,8 @@ void BlobDataBuilder::AppendFile(const base::FilePath& file_path,
scoped_ptr<DataElement> element(new DataElement());
element->SetToFilePathRange(file_path, offset, length,
expected_modification_time);
- items_.push_back(
- new BlobDataItem(element.Pass(), ShareableFileReference::Get(file_path)));
+ items_.push_back(new BlobDataItem(std::move(element),
+ ShareableFileReference::Get(file_path)));
}
void BlobDataBuilder::AppendBlob(const std::string& uuid,
@@ -40,13 +153,13 @@ void BlobDataBuilder::AppendBlob(const std::string& uuid,
DCHECK_GT(length, 0ul);
scoped_ptr<DataElement> element(new DataElement());
element->SetToBlobRange(uuid, offset, length);
- items_.push_back(new BlobDataItem(element.Pass()));
+ items_.push_back(new BlobDataItem(std::move(element)));
}
void BlobDataBuilder::AppendBlob(const std::string& uuid) {
scoped_ptr<DataElement> element(new DataElement());
element->SetToBlob(uuid);
- items_.push_back(new BlobDataItem(element.Pass()));
+ items_.push_back(new BlobDataItem(std::move(element)));
}
void BlobDataBuilder::AppendFileSystemFile(
@@ -54,11 +167,11 @@ void BlobDataBuilder::AppendFileSystemFile(
uint64_t offset,
uint64_t length,
const base::Time& expected_modification_time) {
- DCHECK(length > 0);
+ DCHECK_GT(length, 0ul);
scoped_ptr<DataElement> element(new DataElement());
element->SetToFileSystemUrlRange(url, offset, length,
expected_modification_time);
- items_.push_back(new BlobDataItem(element.Pass()));
+ items_.push_back(new BlobDataItem(std::move(element)));
}
void BlobDataBuilder::AppendDiskCacheEntry(
@@ -68,9 +181,27 @@ void BlobDataBuilder::AppendDiskCacheEntry(
scoped_ptr<DataElement> element(new DataElement());
element->SetToDiskCacheEntryRange(
0U, disk_cache_entry->GetDataSize(disk_cache_stream_index));
- items_.push_back(
- new BlobDataItem(element.Pass(), data_handle, disk_cache_entry,
- disk_cache_stream_index));
+ items_.push_back(new BlobDataItem(std::move(element), data_handle,
+ disk_cache_entry, disk_cache_stream_index));
+}
+
+void BlobDataBuilder::Clear() {
+ items_.clear();
+ content_disposition_.clear();
+ content_type_.clear();
+ uuid_.clear();
+}
+
+void PrintTo(const BlobDataBuilder& x, std::ostream* os) {
+ DCHECK(os);
+ *os << "<BlobDataBuilder>{uuid: " << x.uuid()
+ << ", content_type: " << x.content_type_
+ << ", content_disposition: " << x.content_disposition_ << ", items: [";
+ for (const auto& item : x.items_) {
+ PrintTo(*item, os);
+ *os << ", ";
+ }
+ *os << "]}";
}
} // namespace storage
diff --git a/chromium/storage/browser/blob/blob_data_builder.h b/chromium/storage/browser/blob/blob_data_builder.h
index 115d1f4391a..09601880178 100644
--- a/chromium/storage/browser/blob/blob_data_builder.h
+++ b/chromium/storage/browser/blob/blob_data_builder.h
@@ -5,12 +5,14 @@
#ifndef STORAGE_BROWSER_BLOB_BLOB_DATA_BUILDER_H_
#define STORAGE_BROWSER_BLOB_BLOB_DATA_BUILDER_H_
+#include <stddef.h>
#include <stdint.h>
+#include <ostream>
#include <string>
#include <vector>
-#include "base/basictypes.h"
#include "base/files/file_path.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "storage/browser/blob/blob_data_item.h"
#include "storage/browser/blob/blob_data_snapshot.h"
@@ -22,22 +24,68 @@ class Entry;
namespace storage {
class BlobStorageContext;
+class ShareableFileReference;
class STORAGE_EXPORT BlobDataBuilder {
public:
using DataHandle = BlobDataItem::DataHandle;
+ // This is the filename used for the temporary file items added by
+ // AppendFutureFile.
+ const static char kAppendFutureFileTemporaryFileName[];
+
explicit BlobDataBuilder(const std::string& uuid);
~BlobDataBuilder();
const std::string& uuid() const { return uuid_; }
+ // Validates the data element that was sent over IPC, and copies the data if
+ // it's a 'bytes' element. Data elements of BYTES_DESCRIPTION or
+ // DISK_CACHE_ENTRY types are not valid IPC data element types, and cannot be
+ // given to this method.
+ void AppendIPCDataElement(const DataElement& ipc_data);
+
+ // Copies the given data into the blob.
void AppendData(const std::string& data) {
AppendData(data.c_str(), data.size());
}
+ // Copies the given data into the blob.
void AppendData(const char* data, size_t length);
+ // Adds an item that is flagged for future data population. The memory is not
+ // allocated until the first call to PopulateFutureData. Returns the index of
+ // the item (to be used in PopulateFutureData). |length| cannot be 0.
+ size_t AppendFutureData(size_t length);
+
+ // Populates a part of an item previously allocated with AppendFutureData.
+ // The first call to PopulateFutureData lazily allocates the memory for the
+ // data element.
+ // Returns true if:
+ // * The item was created by using AppendFutureData,
+ // * The offset and length are valid, and
+ // * data is a valid pointer.
+ bool PopulateFutureData(size_t index,
+ const char* data,
+ size_t offset,
+ size_t length);
+
+ // Adds an item that is flagged for future data population. Use
+ // 'PopulateFutureFile' to set the file path and expected modification time
+ // of this file. Returns the index of the item (to be used in
+ // PopulateFutureFile). The temporary filename used by this method is
+ // kAppendFutureFileTemporaryFileName. |length| cannot be 0.
+ size_t AppendFutureFile(uint64_t offset, uint64_t length);
+
+ // Populates a part of an item previously allocated with AppendFutureFile.
+ // Returns true if:
+ // * The item was created by using AppendFutureFile and
+ // * The filepath is valid.
+ bool PopulateFutureFile(
+ size_t index,
+ const scoped_refptr<ShareableFileReference>& file_reference,
+ const base::Time& expected_modification_time);
+
// You must know the length of the file, you cannot use kuint64max to specify
// the whole file. This method creates a ShareableFileReference to the given
// file, which is stored in this builder.
@@ -67,10 +115,15 @@ class STORAGE_EXPORT BlobDataBuilder {
content_disposition_ = content_disposition;
}
+ void Clear();
+
private:
friend class BlobStorageContext;
+ friend class BlobAsyncBuilderHostTest;
friend bool operator==(const BlobDataBuilder& a, const BlobDataBuilder& b);
friend bool operator==(const BlobDataSnapshot& a, const BlobDataBuilder& b);
+ friend STORAGE_EXPORT void PrintTo(const BlobDataBuilder& x,
+ ::std::ostream* os);
std::string uuid_;
std::string content_type_;
@@ -89,7 +142,7 @@ inline bool operator==(const BlobDataBuilder& a, const BlobDataBuilder& b) {
if (a.items_.size() != b.items_.size())
return false;
for (size_t i = 0; i < a.items_.size(); ++i) {
- if (a.items_[i] != b.items_[i])
+ if (*(a.items_[i]) != *(b.items_[i]))
return false;
}
return true;
@@ -119,6 +172,7 @@ inline bool operator!=(const BlobDataSnapshot& a, const BlobDataBuilder& b) {
inline bool operator!=(const BlobDataBuilder& a, const BlobDataBuilder& b) {
return !(a == b);
}
+
#endif // defined(UNIT_TEST)
} // namespace storage
diff --git a/chromium/storage/browser/blob/blob_data_handle.cc b/chromium/storage/browser/blob/blob_data_handle.cc
index 3e864fa1cdf..efe13b16ea5 100644
--- a/chromium/storage/browser/blob/blob_data_handle.cc
+++ b/chromium/storage/browser/blob/blob_data_handle.cc
@@ -4,9 +4,12 @@
#include "storage/browser/blob/blob_data_handle.h"
+#include <stdint.h>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/sequenced_task_runner.h"
#include "base/task_runner.h"
#include "base/time/time.h"
@@ -44,12 +47,8 @@ class FileStreamReaderProviderImpl
int64_t max_bytes_to_read,
const base::Time& expected_modification_time) override {
return file_system_context_->CreateFileStreamReader(
- storage::FileSystemURL(
- file_system_context_->CrackURL(
- filesystem_url)),
- offset, max_bytes_to_read,
- expected_modification_time)
- .Pass();
+ storage::FileSystemURL(file_system_context_->CrackURL(filesystem_url)),
+ offset, max_bytes_to_read, expected_modification_time);
}
private:
@@ -82,7 +81,7 @@ scoped_ptr<BlobReader> BlobDataHandle::CreateReader(
scoped_ptr<BlobDataSnapshot>
BlobDataHandle::BlobDataHandleShared::CreateSnapshot() const {
- return context_->CreateSnapshot(uuid_).Pass();
+ return context_->CreateSnapshot(uuid_);
}
BlobDataHandle::BlobDataHandleShared::~BlobDataHandleShared() {
@@ -118,7 +117,7 @@ BlobDataHandle::~BlobDataHandle() {
scoped_ptr<BlobDataSnapshot> BlobDataHandle::CreateSnapshot() const {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
- return shared_->CreateSnapshot().Pass();
+ return shared_->CreateSnapshot();
}
const std::string& BlobDataHandle::uuid() const {
diff --git a/chromium/storage/browser/blob/blob_data_handle.h b/chromium/storage/browser/blob/blob_data_handle.h
index 8eba2c61fda..7d0bef83ee8 100644
--- a/chromium/storage/browser/blob/blob_data_handle.h
+++ b/chromium/storage/browser/blob/blob_data_handle.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/storage/browser/blob/blob_data_item.cc b/chromium/storage/browser/blob/blob_data_item.cc
index c1ec3b3db68..70495ed7c56 100644
--- a/chromium/storage/browser/blob/blob_data_item.cc
+++ b/chromium/storage/browser/blob/blob_data_item.cc
@@ -4,36 +4,53 @@
#include "storage/browser/blob/blob_data_item.h"
+#include <utility>
+
namespace storage {
BlobDataItem::DataHandle::~DataHandle() {
}
BlobDataItem::BlobDataItem(scoped_ptr<DataElement> item)
- : item_(item.Pass()),
+ : item_(std::move(item)),
disk_cache_entry_(nullptr),
- disk_cache_stream_index_(-1) {
-}
+ disk_cache_stream_index_(-1) {}
BlobDataItem::BlobDataItem(scoped_ptr<DataElement> item,
const scoped_refptr<DataHandle>& data_handle)
- : item_(item.Pass()),
+ : item_(std::move(item)),
data_handle_(data_handle),
disk_cache_entry_(nullptr),
- disk_cache_stream_index_(-1) {
-}
+ disk_cache_stream_index_(-1) {}
BlobDataItem::BlobDataItem(scoped_ptr<DataElement> item,
const scoped_refptr<DataHandle>& data_handle,
disk_cache::Entry* entry,
int disk_cache_stream_index)
- : item_(item.Pass()),
+ : item_(std::move(item)),
data_handle_(data_handle),
disk_cache_entry_(entry),
- disk_cache_stream_index_(disk_cache_stream_index) {
+ disk_cache_stream_index_(disk_cache_stream_index) {}
+
+BlobDataItem::~BlobDataItem() {}
+
+void PrintTo(const BlobDataItem& x, ::std::ostream* os) {
+ DCHECK(os);
+ *os << "<BlobDataItem>{item: ";
+ PrintTo(*x.item_, os);
+ *os << ", has_data_handle: " << (x.data_handle_.get() ? "true" : "false")
+ << ", disk_cache_entry_ptr: " << x.disk_cache_entry_
+ << ", disk_cache_stream_index_: " << x.disk_cache_stream_index_ << "}";
+}
+
+bool operator==(const BlobDataItem& a, const BlobDataItem& b) {
+ return a.disk_cache_entry() == b.disk_cache_entry() &&
+ a.disk_cache_stream_index() == b.disk_cache_stream_index() &&
+ a.data_element() == b.data_element();
}
-BlobDataItem::~BlobDataItem() {
+bool operator!=(const BlobDataItem& a, const BlobDataItem& b) {
+ return !(a == b);
}
} // namespace storage
diff --git a/chromium/storage/browser/blob/blob_data_item.h b/chromium/storage/browser/blob/blob_data_item.h
index 5b25db4db0f..c0495c31078 100644
--- a/chromium/storage/browser/blob/blob_data_item.h
+++ b/chromium/storage/browser/blob/blob_data_item.h
@@ -5,7 +5,11 @@
#ifndef STORAGE_BROWSER_BLOB_BLOB_DATA_ITEM_H_
#define STORAGE_BROWSER_BLOB_BLOB_DATA_ITEM_H_
-#include "base/basictypes.h"
+#include <stdint.h>
+
+#include <ostream>
+#include <string>
+
#include "base/memory/ref_counted.h"
#include "storage/browser/storage_browser_export.h"
#include "storage/common/data_element.h"
@@ -43,13 +47,14 @@ class STORAGE_EXPORT BlobDataItem : public base::RefCounted<BlobDataItem> {
const base::FilePath& path() const { return item_->path(); }
const GURL& filesystem_url() const { return item_->filesystem_url(); }
const std::string& blob_uuid() const { return item_->blob_uuid(); }
- uint64 offset() const { return item_->offset(); }
- uint64 length() const { return item_->length(); }
+ uint64_t offset() const { return item_->offset(); }
+ uint64_t length() const { return item_->length(); }
const base::Time& expected_modification_time() const {
return item_->expected_modification_time();
}
const DataElement& data_element() const { return *item_; }
const DataElement* data_element_ptr() const { return item_.get(); }
+ DataElement* data_element_ptr() { return item_.get(); }
disk_cache::Entry* disk_cache_entry() const { return disk_cache_entry_; }
int disk_cache_stream_index() const { return disk_cache_stream_index_; }
@@ -58,8 +63,9 @@ class STORAGE_EXPORT BlobDataItem : public base::RefCounted<BlobDataItem> {
friend class BlobDataBuilder;
friend class BlobStorageContext;
friend class base::RefCounted<BlobDataItem>;
+ friend STORAGE_EXPORT void PrintTo(const BlobDataItem& x, ::std::ostream* os);
- BlobDataItem(scoped_ptr<DataElement> item);
+ explicit BlobDataItem(scoped_ptr<DataElement> item);
BlobDataItem(scoped_ptr<DataElement> item,
const scoped_refptr<DataHandle>& data_handle);
BlobDataItem(scoped_ptr<DataElement> item,
@@ -77,17 +83,8 @@ class STORAGE_EXPORT BlobDataItem : public base::RefCounted<BlobDataItem> {
int disk_cache_stream_index_; // For TYPE_DISK_CACHE_ENTRY.
};
-#if defined(UNIT_TEST)
-inline bool operator==(const BlobDataItem& a, const BlobDataItem& b) {
- return a.disk_cache_entry() == b.disk_cache_entry() &&
- a.disk_cache_stream_index() == b.disk_cache_stream_index() &&
- a.data_element() == b.data_element();
-}
-
-inline bool operator!=(const BlobDataItem& a, const BlobDataItem& b) {
- return !(a == b);
-}
-#endif // defined(UNIT_TEST)
+STORAGE_EXPORT bool operator==(const BlobDataItem& a, const BlobDataItem& b);
+STORAGE_EXPORT bool operator!=(const BlobDataItem& a, const BlobDataItem& b);
} // namespace storage
diff --git a/chromium/storage/browser/blob/blob_data_snapshot.cc b/chromium/storage/browser/blob/blob_data_snapshot.cc
index 8eb8ee2f57b..0071a11dfd2 100644
--- a/chromium/storage/browser/blob/blob_data_snapshot.cc
+++ b/chromium/storage/browser/blob/blob_data_snapshot.cc
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <stddef.h>
+#include <stdint.h>
+
#include "storage/browser/blob/blob_data_snapshot.h"
namespace storage {
@@ -36,7 +39,7 @@ BlobDataSnapshot::~BlobDataSnapshot() {
}
size_t BlobDataSnapshot::GetMemoryUsage() const {
- int64 memory = 0;
+ int64_t memory = 0;
for (const auto& data_item : items_) {
if (data_item->type() == DataElement::TYPE_BYTES)
memory += data_item->length();
diff --git a/chromium/storage/browser/blob/blob_data_snapshot.h b/chromium/storage/browser/blob/blob_data_snapshot.h
index 01ea2ef295e..31b2973d4c1 100644
--- a/chromium/storage/browser/blob/blob_data_snapshot.h
+++ b/chromium/storage/browser/blob/blob_data_snapshot.h
@@ -5,6 +5,8 @@
#ifndef STORAGE_BROWSER_BLOB_BLOB_DATA_SNAPSHOT_H_
#define STORAGE_BROWSER_BLOB_BLOB_DATA_SNAPSHOT_H_
+#include <stddef.h>
+
#include <string>
#include <vector>
diff --git a/chromium/storage/browser/blob/blob_reader.cc b/chromium/storage/browser/blob/blob_reader.cc
index ccb4e55a0cd..6e3e866ba75 100644
--- a/chromium/storage/browser/blob/blob_reader.cc
+++ b/chromium/storage/browser/blob/blob_reader.cc
@@ -4,8 +4,11 @@
#include "storage/browser/blob/blob_reader.h"
+#include <stddef.h>
+#include <stdint.h>
#include <algorithm>
#include <limits>
+#include <utility>
#include "base/bind.h"
#include "base/sequenced_task_runner.h"
@@ -41,12 +44,12 @@ BlobReader::BlobReader(
const BlobDataHandle* blob_handle,
scoped_ptr<FileStreamReaderProvider> file_stream_provider,
base::SequencedTaskRunner* file_task_runner)
- : file_stream_provider_(file_stream_provider.Pass()),
+ : file_stream_provider_(std::move(file_stream_provider)),
file_task_runner_(file_task_runner),
net_error_(net::OK),
weak_factory_(this) {
if (blob_handle) {
- blob_data_ = blob_handle->CreateSnapshot().Pass();
+ blob_data_ = blob_handle->CreateSnapshot();
}
}
@@ -240,11 +243,11 @@ bool BlobReader::ResolveFileItemLength(const BlobDataItem& item,
return false;
}
- uint64 max_length = file_length - item_offset;
+ uint64_t max_length = file_length - item_offset;
// If item length is undefined, then we need to use the file size being
// resolved in the real time.
- if (item_length == std::numeric_limits<uint64>::max()) {
+ if (item_length == std::numeric_limits<uint64_t>::max()) {
item_length = max_length;
} else if (item_length > max_length) {
return false;
@@ -524,21 +527,18 @@ scoped_ptr<FileStreamReader> BlobReader::CreateFileStreamReader(
switch (item.type()) {
case DataElement::TYPE_FILE:
return file_stream_provider_->CreateForLocalFile(
- file_task_runner_.get(), item.path(),
- item.offset() + additional_offset,
- item.expected_modification_time())
- .Pass();
+ file_task_runner_.get(), item.path(),
+ item.offset() + additional_offset, item.expected_modification_time());
case DataElement::TYPE_FILE_FILESYSTEM:
- return file_stream_provider_
- ->CreateFileStreamReader(
- item.filesystem_url(), item.offset() + additional_offset,
- item.length() == std::numeric_limits<uint64_t>::max()
- ? storage::kMaximumLength
- : item.length() - additional_offset,
- item.expected_modification_time())
- .Pass();
+ return file_stream_provider_->CreateFileStreamReader(
+ item.filesystem_url(), item.offset() + additional_offset,
+ item.length() == std::numeric_limits<uint64_t>::max()
+ ? storage::kMaximumLength
+ : item.length() - additional_offset,
+ item.expected_modification_time());
case DataElement::TYPE_BLOB:
case DataElement::TYPE_BYTES:
+ case DataElement::TYPE_BYTES_DESCRIPTION:
case DataElement::TYPE_DISK_CACHE_ENTRY:
case DataElement::TYPE_UNKNOWN:
break;
diff --git a/chromium/storage/browser/blob/blob_reader.h b/chromium/storage/browser/blob/blob_reader.h
index 54b262f3ef3..0756f0fc1cf 100644
--- a/chromium/storage/browser/blob/blob_reader.h
+++ b/chromium/storage/browser/blob/blob_reader.h
@@ -5,6 +5,7 @@
#ifndef STORAGE_BROWSER_BLOB_BLOB_READER_H_
#define STORAGE_BROWSER_BLOB_BLOB_READER_H_
+#include <stddef.h>
#include <stdint.h>
#include <map>
#include <vector>
diff --git a/chromium/storage/browser/blob/blob_storage_context.cc b/chromium/storage/browser/blob/blob_storage_context.cc
index 711469690d3..e8fc0085cdf 100644
--- a/chromium/storage/browser/blob/blob_storage_context.cc
+++ b/chromium/storage/browser/blob/blob_storage_context.cc
@@ -4,8 +4,11 @@
#include "storage/browser/blob/blob_storage_context.h"
+#include <stddef.h>
+#include <stdint.h>
#include <algorithm>
#include <limits>
+#include <utility>
#include "base/bind.h"
#include "base/location.h"
@@ -41,7 +44,7 @@ GURL ClearBlobUrlRef(const GURL& url) {
// TODO(michaeln): use base::SysInfo::AmountOfPhysicalMemoryMB() in some
// way to come up with a better limit.
-static const int64 kMaxMemoryUsage = 500 * 1024 * 1024; // Half a gig.
+static const int64_t kMaxMemoryUsage = 500 * 1024 * 1024; // Half a gig.
} // namespace
@@ -72,15 +75,15 @@ scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID(
scoped_ptr<BlobDataHandle> result;
BlobMap::iterator found = blob_map_.find(uuid);
if (found == blob_map_.end())
- return result.Pass();
+ return result;
auto* entry = found->second;
if (entry->flags & EXCEEDED_MEMORY)
- return result.Pass();
+ return result;
DCHECK(!entry->IsBeingBuilt());
result.reset(new BlobDataHandle(uuid, entry->data->content_type(),
entry->data->content_disposition(), this,
base::ThreadTaskRunnerHandle::Get().get()));
- return result.Pass();
+ return result;
}
scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromPublicURL(
@@ -93,30 +96,36 @@ scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromPublicURL(
}
scoped_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob(
- BlobDataBuilder* external_builder) {
+ const BlobDataBuilder& external_builder) {
TRACE_EVENT0("Blob", "Context::AddFinishedBlob");
- StartBuildingBlob(external_builder->uuid_);
- BlobMap::iterator found = blob_map_.find(external_builder->uuid_);
+ StartBuildingBlob(external_builder.uuid_);
+ BlobMap::iterator found = blob_map_.find(external_builder.uuid_);
DCHECK(found != blob_map_.end());
BlobMapEntry* entry = found->second;
InternalBlobData::Builder* target_blob_builder = entry->data_builder.get();
DCHECK(target_blob_builder);
target_blob_builder->set_content_disposition(
- external_builder->content_disposition_);
- for (const auto& blob_item : external_builder->items_) {
- if (!AppendAllocatedBlobItem(external_builder->uuid_, blob_item,
+ external_builder.content_disposition_);
+ for (const auto& blob_item : external_builder.items_) {
+ if (!AppendAllocatedBlobItem(external_builder.uuid_, blob_item,
target_blob_builder)) {
BlobEntryExceededMemory(entry);
break;
}
}
- FinishBuildingBlob(external_builder->uuid_, external_builder->content_type_);
+ FinishBuildingBlob(external_builder.uuid_, external_builder.content_type_);
scoped_ptr<BlobDataHandle> handle =
- GetBlobDataFromUUID(external_builder->uuid_);
- DecrementBlobRefCount(external_builder->uuid_);
- return handle.Pass();
+ GetBlobDataFromUUID(external_builder.uuid_);
+ DecrementBlobRefCount(external_builder.uuid_);
+ return handle;
+}
+
+scoped_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob(
+ const BlobDataBuilder* builder) {
+ DCHECK(builder);
+ return AddFinishedBlob(*builder);
}
bool BlobStorageContext::RegisterPublicBlobURL(const GURL& blob_url,
@@ -258,31 +267,31 @@ scoped_refptr<BlobDataItem> BlobStorageContext::AllocateBlobItem(
const DataElement& ipc_data) {
scoped_refptr<BlobDataItem> blob_item;
- uint64 length = ipc_data.length();
+ uint64_t length = ipc_data.length();
scoped_ptr<DataElement> element(new DataElement());
switch (ipc_data.type()) {
case DataElement::TYPE_BYTES:
DCHECK(!ipc_data.offset());
element->SetToBytes(ipc_data.bytes(), length);
- blob_item = new BlobDataItem(element.Pass());
+ blob_item = new BlobDataItem(std::move(element));
break;
case DataElement::TYPE_FILE:
element->SetToFilePathRange(ipc_data.path(), ipc_data.offset(), length,
ipc_data.expected_modification_time());
blob_item = new BlobDataItem(
- element.Pass(), ShareableFileReference::Get(ipc_data.path()));
+ std::move(element), ShareableFileReference::Get(ipc_data.path()));
break;
case DataElement::TYPE_FILE_FILESYSTEM:
element->SetToFileSystemUrlRange(ipc_data.filesystem_url(),
ipc_data.offset(), length,
ipc_data.expected_modification_time());
- blob_item = new BlobDataItem(element.Pass());
+ blob_item = new BlobDataItem(std::move(element));
break;
case DataElement::TYPE_BLOB:
// This is a temporary item that will be deconstructed later.
element->SetToBlobRange(ipc_data.blob_uuid(), ipc_data.offset(),
ipc_data.length());
- blob_item = new BlobDataItem(element.Pass());
+ blob_item = new BlobDataItem(std::move(element));
break;
case DataElement::TYPE_DISK_CACHE_ENTRY: // This type can't be sent by IPC.
NOTREACHED();
@@ -315,8 +324,8 @@ bool BlobStorageContext::AppendAllocatedBlobItem(
// portion of the item is copied.
const DataElement& data_element = blob_item->data_element();
- uint64 length = data_element.length();
- uint64 offset = data_element.offset();
+ uint64_t length = data_element.length();
+ uint64_t offset = data_element.offset();
UMA_HISTOGRAM_COUNTS("Storage.Blob.StorageSizeBeforeAppend",
memory_usage_ / 1024);
switch (data_element.type()) {
@@ -332,7 +341,7 @@ bool BlobStorageContext::AppendAllocatedBlobItem(
new ShareableBlobDataItem(target_blob_uuid, blob_item));
break;
case DataElement::TYPE_FILE: {
- bool full_file = (length == std::numeric_limits<uint64>::max());
+ bool full_file = (length == std::numeric_limits<uint64_t>::max());
UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.File.Unknown", full_file);
if (!full_file) {
UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.File",
@@ -343,7 +352,7 @@ bool BlobStorageContext::AppendAllocatedBlobItem(
break;
}
case DataElement::TYPE_FILE_FILESYSTEM: {
- bool full_file = (length == std::numeric_limits<uint64>::max());
+ bool full_file = (length == std::numeric_limits<uint64_t>::max());
UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.FileSystem.Unknown",
full_file);
if (!full_file) {
@@ -435,13 +444,13 @@ bool BlobStorageContext::AppendBlob(
DCHECK(!item.offset());
scoped_ptr<DataElement> element(new DataElement());
element->SetToBytes(item.bytes() + offset,
- static_cast<int64>(new_length));
+ static_cast<int64_t>(new_length));
memory_usage_ += new_length;
target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
- target_blob_uuid, new BlobDataItem(element.Pass())));
+ target_blob_uuid, new BlobDataItem(std::move(element))));
} break;
case DataElement::TYPE_FILE: {
- DCHECK_NE(item.length(), std::numeric_limits<uint64>::max())
+ DCHECK_NE(item.length(), std::numeric_limits<uint64_t>::max())
<< "We cannot use a section of a file with an unknown length";
UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.File",
new_length / 1024);
@@ -451,7 +460,7 @@ bool BlobStorageContext::AppendBlob(
item.expected_modification_time());
target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
target_blob_uuid,
- new BlobDataItem(element.Pass(), item.data_handle_)));
+ new BlobDataItem(std::move(element), item.data_handle_)));
} break;
case DataElement::TYPE_FILE_FILESYSTEM: {
UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.FileSystem",
@@ -461,7 +470,7 @@ bool BlobStorageContext::AppendBlob(
item.offset() + offset, new_length,
item.expected_modification_time());
target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
- target_blob_uuid, new BlobDataItem(element.Pass())));
+ target_blob_uuid, new BlobDataItem(std::move(element))));
} break;
case DataElement::TYPE_DISK_CACHE_ENTRY: {
scoped_ptr<DataElement> element(new DataElement());
@@ -469,7 +478,7 @@ bool BlobStorageContext::AppendBlob(
new_length);
target_blob_builder->AppendSharedBlobItem(new ShareableBlobDataItem(
target_blob_uuid,
- new BlobDataItem(element.Pass(), item.data_handle_,
+ new BlobDataItem(std::move(element), item.data_handle_,
item.disk_cache_entry(),
item.disk_cache_stream_index())));
} break;
diff --git a/chromium/storage/browser/blob/blob_storage_context.h b/chromium/storage/browser/blob/blob_storage_context.h
index cf73c8a28f8..54cff9b2a86 100644
--- a/chromium/storage/browser/blob/blob_storage_context.h
+++ b/chromium/storage/browser/blob/blob_storage_context.h
@@ -5,10 +5,14 @@
#ifndef STORAGE_BROWSER_BLOB_BLOB_STORAGE_CONTEXT_H_
#define STORAGE_BROWSER_BLOB_BLOB_STORAGE_CONTEXT_H_
+#include <stddef.h>
+#include <stdint.h>
+
#include <map>
#include <string>
#include <vector>
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "storage/browser/blob/blob_data_handle.h"
@@ -55,7 +59,10 @@ class STORAGE_EXPORT BlobStorageContext
// To cleanly use a builder multiple times, please call Clone() on the
// builder, or even better for memory savings, clear the builder and append
// the previously constructed blob.
- scoped_ptr<BlobDataHandle> AddFinishedBlob(BlobDataBuilder* builder);
+ scoped_ptr<BlobDataHandle> AddFinishedBlob(const BlobDataBuilder& builder);
+
+ // Deprecated, use const ref version above.
+ scoped_ptr<BlobDataHandle> AddFinishedBlob(const BlobDataBuilder* builder);
// Useful for coining blob urls from within the browser process.
bool RegisterPublicBlobURL(const GURL& url, const std::string& uuid);
diff --git a/chromium/storage/browser/blob/blob_storage_registry.cc b/chromium/storage/browser/blob/blob_storage_registry.cc
new file mode 100644
index 00000000000..8ee624f7cec
--- /dev/null
+++ b/chromium/storage/browser/blob/blob_storage_registry.cc
@@ -0,0 +1,118 @@
+// Copyright 2015 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 "storage/browser/blob/blob_storage_registry.h"
+
+#include <stddef.h>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/stl_util.h"
+#include "url/gurl.h"
+
+namespace storage {
+using BlobState = BlobStorageRegistry::BlobState;
+
+namespace {
+// We can't use GURL directly for these hash fragment manipulations
+// since it doesn't have specific knowlege of the BlobURL format. GURL
+// treats BlobURLs as if they were PathURLs which don't support hash
+// fragments.
+
+bool BlobUrlHasRef(const GURL& url) {
+ return url.spec().find('#') != std::string::npos;
+}
+
+GURL ClearBlobUrlRef(const GURL& url) {
+ size_t hash_pos = url.spec().find('#');
+ if (hash_pos == std::string::npos)
+ return url;
+ return GURL(url.spec().substr(0, hash_pos));
+}
+
+} // namespace
+
+BlobStorageRegistry::Entry::Entry(int refcount, BlobState state)
+ : refcount(refcount), state(state), exceeded_memory(false) {}
+
+BlobStorageRegistry::Entry::~Entry() {}
+
+bool BlobStorageRegistry::Entry::TestAndSetState(BlobState expected,
+ BlobState set) {
+ if (state != expected)
+ return false;
+ state = set;
+ return true;
+}
+
+BlobStorageRegistry::BlobStorageRegistry() {}
+
+BlobStorageRegistry::~BlobStorageRegistry() {
+ // Note: We don't bother calling the construction complete callbacks, as we
+ // are only being destructed at the end of the life of the browser process.
+ // So it shouldn't matter.
+}
+
+BlobStorageRegistry::Entry* BlobStorageRegistry::CreateEntry(
+ const std::string& uuid) {
+ DCHECK(!ContainsKey(blob_map_, uuid));
+ Entry* entry = new Entry(1, BlobState::RESERVED);
+ blob_map_.add(uuid, make_scoped_ptr(entry));
+ return entry;
+}
+
+bool BlobStorageRegistry::DeleteEntry(const std::string& uuid) {
+ return blob_map_.erase(uuid) == 1;
+}
+
+BlobStorageRegistry::Entry* BlobStorageRegistry::GetEntry(
+ const std::string& uuid) {
+ BlobMap::iterator found = blob_map_.find(uuid);
+ if (found == blob_map_.end())
+ return nullptr;
+ return found->second;
+}
+
+bool BlobStorageRegistry::CreateUrlMapping(const GURL& blob_url,
+ const std::string& uuid) {
+ DCHECK(!BlobUrlHasRef(blob_url));
+ if (blob_map_.find(uuid) == blob_map_.end() || IsURLMapped(blob_url))
+ return false;
+ url_to_uuid_[blob_url] = uuid;
+ return true;
+}
+
+bool BlobStorageRegistry::DeleteURLMapping(const GURL& blob_url,
+ std::string* uuid) {
+ DCHECK(!BlobUrlHasRef(blob_url));
+ URLMap::iterator found = url_to_uuid_.find(blob_url);
+ if (found == url_to_uuid_.end())
+ return false;
+ if (uuid)
+ uuid->assign(found->second);
+ url_to_uuid_.erase(found);
+ return true;
+}
+
+bool BlobStorageRegistry::IsURLMapped(const GURL& blob_url) const {
+ return ContainsKey(url_to_uuid_, blob_url);
+}
+
+BlobStorageRegistry::Entry* BlobStorageRegistry::GetEntryFromURL(
+ const GURL& url,
+ std::string* uuid) {
+ URLMap::iterator found =
+ url_to_uuid_.find(BlobUrlHasRef(url) ? ClearBlobUrlRef(url) : url);
+ if (found == url_to_uuid_.end())
+ return nullptr;
+ Entry* entry = GetEntry(found->second);
+ if (entry && uuid)
+ uuid->assign(found->second);
+ return entry;
+}
+
+} // namespace storage
diff --git a/chromium/storage/browser/blob/blob_storage_registry.h b/chromium/storage/browser/blob/blob_storage_registry.h
new file mode 100644
index 00000000000..54e8b0e0d05
--- /dev/null
+++ b/chromium/storage/browser/blob/blob_storage_registry.h
@@ -0,0 +1,110 @@
+// Copyright 2015 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 STORAGE_BROWSER_BLOB_BLOB_STORAGE_REGISTRY_H_
+#define STORAGE_BROWSER_BLOB_BLOB_STORAGE_REGISTRY_H_
+
+#include <stddef.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/macros.h"
+#include "storage/browser/blob/internal_blob_data.h"
+#include "storage/browser/storage_browser_export.h"
+
+class GURL;
+
+namespace storage {
+
+// This class stores the blob data in the various states of construction, as
+// well as URL mappings to blob uuids.
+// Implementation notes:
+// * There is no implicit refcounting in this class, except for setting the
+// refcount to 1 on registration.
+// * When removing a uuid registration, we do not check for URL mappings to that
+// uuid. The user must keep track of these.
+class STORAGE_EXPORT BlobStorageRegistry {
+ public:
+ enum class BlobState {
+ // First the renderer reserves the uuid.
+ RESERVED = 1,
+ // Second, we are asynchronously transporting data to the browser.
+ ASYNC_TRANSPORTATION,
+ // Third, we construct the blob when we have all of the data.
+ CONSTRUCTION,
+ // Finally, the blob is built.
+ ACTIVE
+ };
+
+ struct STORAGE_EXPORT Entry {
+ size_t refcount;
+ BlobState state;
+ std::vector<base::Callback<void(bool)>> construction_complete_callbacks;
+
+ // Flags
+ bool exceeded_memory;
+
+ // data and data_builder are mutually exclusive.
+ scoped_ptr<InternalBlobData> data;
+ scoped_ptr<InternalBlobData::Builder> data_builder;
+
+ Entry() = delete;
+ Entry(int refcount, BlobState state);
+ ~Entry();
+
+ // Performs a test-and-set on the state of the given blob. If the state
+ // isn't as expected, we return false. Otherwise we set the new state and
+ // return true.
+ bool TestAndSetState(BlobState expected, BlobState set);
+ };
+
+ BlobStorageRegistry();
+ ~BlobStorageRegistry();
+
+ // Creates the blob entry with a refcount of 1 and a state of RESERVED. If
+ // the blob is already in use, we return null.
+ Entry* CreateEntry(const std::string& uuid);
+
+ // Removes the blob entry with the given uuid. This does not unmap any
+ // URLs that are pointing to this uuid. Returns if the entry existed.
+ bool DeleteEntry(const std::string& uuid);
+
+ // Gets the blob entry for the given uuid. Returns nullptr if the entry
+ // does not exist.
+ Entry* GetEntry(const std::string& uuid);
+
+ // Creates a url mapping from blob uuid to the given url. Returns false if
+ // the uuid isn't mapped to an entry or if there already is a map for the URL.
+ bool CreateUrlMapping(const GURL& url, const std::string& uuid);
+
+ // Removes the given URL mapping. Optionally populates a uuid string of the
+ // removed entry uuid. Returns false if the url isn't mapped.
+ bool DeleteURLMapping(const GURL& url, std::string* uuid);
+
+ // Returns if the url is mapped to a blob uuid.
+ bool IsURLMapped(const GURL& blob_url) const;
+
+ // Returns the entry from the given url, and optionally populates the uuid for
+ // that entry. Returns a nullptr if the mapping or entry doesn't exist.
+ Entry* GetEntryFromURL(const GURL& url, std::string* uuid);
+
+ size_t blob_count() const { return blob_map_.size(); }
+ size_t url_count() const { return url_to_uuid_.size(); }
+
+ private:
+ using BlobMap = base::ScopedPtrHashMap<std::string, scoped_ptr<Entry>>;
+ using URLMap = std::map<GURL, std::string>;
+
+ BlobMap blob_map_;
+ URLMap url_to_uuid_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlobStorageRegistry);
+};
+
+} // namespace storage
+#endif // STORAGE_BROWSER_BLOB_BLOB_STORAGE_REGISTRY_H_
diff --git a/chromium/storage/browser/blob/blob_url_request_job.cc b/chromium/storage/browser/blob/blob_url_request_job.cc
index 6ec2fe57ae7..783c3866ba5 100644
--- a/chromium/storage/browser/blob/blob_url_request_job.cc
+++ b/chromium/storage/browser/blob/blob_url_request_job.cc
@@ -4,12 +4,13 @@
#include "storage/browser/blob/blob_url_request_job.h"
+#include <stdint.h>
+
#include <algorithm>
#include <limits>
#include <string>
#include <vector>
-#include "base/basictypes.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/files/file_util_proxy.h"
@@ -75,41 +76,37 @@ void BlobURLRequestJob::Kill() {
weak_factory_.InvalidateWeakPtrs();
}
-bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest,
- int dest_size,
- int* bytes_read) {
+int BlobURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size) {
TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadRawData", this, "uuid",
blob_handle_ ? blob_handle_->uuid() : "NotFound");
DCHECK_NE(dest_size, 0);
- DCHECK(bytes_read);
- // Bail out immediately if we encounter an error.
- if (error_) {
- *bytes_read = 0;
- return true;
- }
+ // Bail out immediately if we encounter an error. This happens if a previous
+ // ReadRawData signalled an error to its caller but the caller called
+ // ReadRawData again anyway.
+ if (error_)
+ return 0;
+ int bytes_read = 0;
BlobReader::Status read_status =
- blob_reader_->Read(dest, dest_size, bytes_read,
+ blob_reader_->Read(dest, dest_size, &bytes_read,
base::Bind(&BlobURLRequestJob::DidReadRawData,
weak_factory_.GetWeakPtr()));
switch (read_status) {
case BlobReader::Status::NET_ERROR:
- NotifyFailure(blob_reader_->net_error());
TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid",
blob_handle_ ? blob_handle_->uuid() : "NotFound");
- return false;
+ return blob_reader_->net_error();
case BlobReader::Status::IO_PENDING:
- SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
- return false;
+ return net::ERR_IO_PENDING;
case BlobReader::Status::DONE:
TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid",
blob_handle_ ? blob_handle_->uuid() : "NotFound");
- return true;
+ return bytes_read;
}
NOTREACHED();
- return true;
+ return 0;
}
bool BlobURLRequestJob::GetMimeType(std::string* mime_type) const {
@@ -222,13 +219,7 @@ void BlobURLRequestJob::DidCalculateSize(int result) {
void BlobURLRequestJob::DidReadRawData(int result) {
TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid",
blob_handle_ ? blob_handle_->uuid() : "NotFound");
- if (result < 0) {
- NotifyFailure(result);
- return;
- }
- // Clear the IO_PENDING status
- SetStatus(net::URLRequestStatus());
- NotifyReadComplete(result);
+ ReadRawDataComplete(result);
}
void BlobURLRequestJob::NotifyFailure(int error_code) {
@@ -236,11 +227,7 @@ void BlobURLRequestJob::NotifyFailure(int error_code) {
// If we already return the headers on success, we can't change the headers
// now. Instead, we just error out.
- if (response_info_) {
- NotifyDone(
- net::URLRequestStatus(net::URLRequestStatus::FAILED, error_code));
- return;
- }
+ DCHECK(!response_info_) << "Cannot NotifyFailure after headers.";
net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR;
switch (error_code) {
diff --git a/chromium/storage/browser/blob/blob_url_request_job.h b/chromium/storage/browser/blob/blob_url_request_job.h
index 21baa2cea9d..70f035684fc 100644
--- a/chromium/storage/browser/blob/blob_url_request_job.h
+++ b/chromium/storage/browser/blob/blob_url_request_job.h
@@ -5,9 +5,12 @@
#ifndef STORAGE_BROWSER_BLOB_BLOB_URL_REQUEST_JOB_H_
#define STORAGE_BROWSER_BLOB_BLOB_URL_REQUEST_JOB_H_
+#include <stddef.h>
+
#include <map>
#include <vector>
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "net/http/http_byte_range.h"
@@ -44,7 +47,7 @@ class STORAGE_EXPORT BlobURLRequestJob
// net::URLRequestJob methods.
void Start() override;
void Kill() override;
- bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override;
+ int ReadRawData(net::IOBuffer* buf, int buf_size) override;
bool GetMimeType(std::string* mime_type) const override;
void GetResponseInfo(net::HttpResponseInfo* info) override;
int GetResponseCode() const override;
diff --git a/chromium/storage/browser/blob/blob_url_request_job_factory.cc b/chromium/storage/browser/blob/blob_url_request_job_factory.cc
index 5961697873d..ed9c137af22 100644
--- a/chromium/storage/browser/blob/blob_url_request_job_factory.cc
+++ b/chromium/storage/browser/blob/blob_url_request_job_factory.cc
@@ -4,7 +4,8 @@
#include "storage/browser/blob/blob_url_request_job_factory.h"
-#include "base/basictypes.h"
+#include <utility>
+
#include "base/strings/string_util.h"
#include "net/base/request_priority.h"
#include "net/url_request/url_request_context.h"
@@ -29,8 +30,8 @@ scoped_ptr<net::URLRequest> BlobProtocolHandler::CreateBlobRequest(
const GURL kBlobUrl("blob://see_user_data/");
scoped_ptr<net::URLRequest> request = request_context->CreateRequest(
kBlobUrl, net::DEFAULT_PRIORITY, request_delegate);
- SetRequestedBlobDataHandle(request.get(), blob_data_handle.Pass());
- return request.Pass();
+ SetRequestedBlobDataHandle(request.get(), std::move(blob_data_handle));
+ return request;
}
// static
@@ -85,7 +86,7 @@ BlobDataHandle* BlobProtocolHandler::LookupBlobHandle(
scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(uuid);
BlobDataHandle* handle_ptr = handle.get();
if (handle) {
- SetRequestedBlobDataHandle(request, handle.Pass());
+ SetRequestedBlobDataHandle(request, std::move(handle));
}
return handle_ptr;
}
diff --git a/chromium/storage/browser/blob/blob_url_request_job_factory.h b/chromium/storage/browser/blob/blob_url_request_job_factory.h
index dcb2fd6784b..326da9b6f18 100644
--- a/chromium/storage/browser/blob/blob_url_request_job_factory.h
+++ b/chromium/storage/browser/blob/blob_url_request_job_factory.h
@@ -6,6 +6,7 @@
#define STORAGE_BROWSER_BLOB_BLOB_URL_REQUEST_JOB_FACTORY_H_
#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "net/url_request/url_request.h"
diff --git a/chromium/storage/browser/blob/internal_blob_data.cc b/chromium/storage/browser/blob/internal_blob_data.cc
index 8441f89e552..cbec2900d69 100644
--- a/chromium/storage/browser/blob/internal_blob_data.cc
+++ b/chromium/storage/browser/blob/internal_blob_data.cc
@@ -4,6 +4,9 @@
#include "storage/browser/blob/internal_blob_data.h"
+#include <stddef.h>
+#include <utility>
+
#include "base/containers/hash_tables.h"
#include "base/metrics/histogram.h"
#include "storage/browser/blob/blob_data_item.h"
@@ -48,7 +51,7 @@ size_t InternalBlobData::Builder::GetNonsharedMemoryUsage() const {
scoped_ptr<InternalBlobData> InternalBlobData::Builder::Build() {
DCHECK(data_);
- return data_.Pass();
+ return std::move(data_);
}
InternalBlobData::InternalBlobData() {
diff --git a/chromium/storage/browser/blob/internal_blob_data.h b/chromium/storage/browser/blob/internal_blob_data.h
index aa47101a987..c751762a6a1 100644
--- a/chromium/storage/browser/blob/internal_blob_data.h
+++ b/chromium/storage/browser/blob/internal_blob_data.h
@@ -5,6 +5,8 @@
#ifndef STORAGE_BROWSER_BLOB_INTERNAL_BLOB_DATA_H_
#define STORAGE_BROWSER_BLOB_INTERNAL_BLOB_DATA_H_
+#include <stddef.h>
+
#include <string>
#include <vector>
@@ -23,6 +25,7 @@ class InternalBlobData {
protected:
friend class BlobStorageContext;
+ friend class BlobStorageRegistry;
friend class ViewBlobInternalsJob;
// Removes the given blob uuid from the internal ShareableBlobDataItems.
diff --git a/chromium/storage/browser/blob/scoped_file.cc b/chromium/storage/browser/blob/scoped_file.cc
index 825dc041198..b57e88208f9 100644
--- a/chromium/storage/browser/blob/scoped_file.cc
+++ b/chromium/storage/browser/blob/scoped_file.cc
@@ -29,8 +29,8 @@ ScopedFile::ScopedFile(const base::FilePath& path,
<< " runner:" << file_task_runner.get();
}
-ScopedFile::ScopedFile(RValue other) {
- MoveFrom(*other.object);
+ScopedFile::ScopedFile(ScopedFile&& other) {
+ MoveFrom(other);
}
ScopedFile::~ScopedFile() {
diff --git a/chromium/storage/browser/blob/scoped_file.h b/chromium/storage/browser/blob/scoped_file.h
index a8fd730efce..583ce783927 100644
--- a/chromium/storage/browser/blob/scoped_file.h
+++ b/chromium/storage/browser/blob/scoped_file.h
@@ -27,10 +27,7 @@ namespace storage {
// TODO(kinuko): Probably this can be moved under base or somewhere more
// common place.
class STORAGE_EXPORT ScopedFile {
- // To support destructive assignment from an l-value assignment.
- // This provides Pass() method which creates an r-value for the current
- // instance. (See base/move.h for details)
- MOVE_ONLY_TYPE_FOR_CPP_03(ScopedFile, RValue)
+ MOVE_ONLY_TYPE_FOR_CPP_03(ScopedFile)
public:
typedef base::Callback<void(const base::FilePath&)> ScopeOutCallback;
@@ -53,9 +50,9 @@ class STORAGE_EXPORT ScopedFile {
// Move constructor and operator. The data of r-value will be transfered
// in a destructive way. (See base/move.h)
- ScopedFile(RValue other);
- ScopedFile& operator=(RValue rhs) {
- MoveFrom(*rhs.object);
+ ScopedFile(ScopedFile&& other);
+ ScopedFile& operator=(ScopedFile&& rhs) {
+ MoveFrom(rhs);
return *this;
}
diff --git a/chromium/storage/browser/blob/shareable_file_reference.cc b/chromium/storage/browser/blob/shareable_file_reference.cc
index e6602391f19..c8672f76d44 100644
--- a/chromium/storage/browser/blob/shareable_file_reference.cc
+++ b/chromium/storage/browser/blob/shareable_file_reference.cc
@@ -5,8 +5,10 @@
#include "storage/browser/blob/shareable_file_reference.h"
#include <map>
+#include <utility>
#include "base/lazy_instance.h"
+#include "base/macros.h"
#include "base/task_runner.h"
#include "base/threading/non_thread_safe.h"
@@ -96,7 +98,7 @@ scoped_refptr<ShareableFileReference> ShareableFileReference::GetOrCreate(
// Wasn't in the map, create a new reference and store the pointer.
scoped_refptr<ShareableFileReference> reference(
- new ShareableFileReference(scoped_file.Pass()));
+ new ShareableFileReference(std::move(scoped_file)));
result.first->second = reference.get();
return reference;
}
@@ -108,7 +110,7 @@ void ShareableFileReference::AddFinalReleaseCallback(
}
ShareableFileReference::ShareableFileReference(ScopedFile scoped_file)
- : scoped_file_(scoped_file.Pass()) {
+ : scoped_file_(std::move(scoped_file)) {
DCHECK(g_file_map.Get().Find(path())->second == NULL);
}
diff --git a/chromium/storage/browser/blob/shareable_file_reference.h b/chromium/storage/browser/blob/shareable_file_reference.h
index 10f986faa13..084c46f342c 100644
--- a/chromium/storage/browser/blob/shareable_file_reference.h
+++ b/chromium/storage/browser/blob/shareable_file_reference.h
@@ -5,6 +5,7 @@
#ifndef STORAGE_BROWSER_BLOB_SHAREABLE_FILE_REFERENCE_H_
#define STORAGE_BROWSER_BLOB_SHAREABLE_FILE_REFERENCE_H_
+#include "base/macros.h"
#include "storage/browser/blob/blob_data_item.h"
#include "storage/browser/blob/scoped_file.h"
#include "storage/browser/storage_browser_export.h"
diff --git a/chromium/storage/browser/blob/upload_blob_element_reader.cc b/chromium/storage/browser/blob/upload_blob_element_reader.cc
index e4d6d4a591d..3c86051f92d 100644
--- a/chromium/storage/browser/blob/upload_blob_element_reader.cc
+++ b/chromium/storage/browser/blob/upload_blob_element_reader.cc
@@ -4,6 +4,9 @@
#include "storage/browser/blob/upload_blob_element_reader.h"
+#include <stdint.h>
+#include <utility>
+
#include "base/single_thread_task_runner.h"
#include "net/base/net_errors.h"
#include "storage/browser/blob/blob_data_handle.h"
@@ -16,7 +19,7 @@ UploadBlobElementReader::UploadBlobElementReader(
scoped_ptr<BlobDataHandle> handle,
FileSystemContext* file_system_context,
base::SingleThreadTaskRunner* file_task_runner)
- : handle_(handle.Pass()),
+ : handle_(std::move(handle)),
file_system_context_(file_system_context),
file_runner_(file_task_runner) {}
diff --git a/chromium/storage/browser/blob/upload_blob_element_reader.h b/chromium/storage/browser/blob/upload_blob_element_reader.h
index 47ff90d2cbc..f8192d0603f 100644
--- a/chromium/storage/browser/blob/upload_blob_element_reader.h
+++ b/chromium/storage/browser/blob/upload_blob_element_reader.h
@@ -5,6 +5,8 @@
#ifndef STORAGE_BROWSER_BLOB_UPLOAD_BLOB_ELEMENT_READER_H_
#define STORAGE_BROWSER_BLOB_UPLOAD_BLOB_ELEMENT_READER_H_
+#include <stdint.h>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
diff --git a/chromium/storage/browser/blob/view_blob_internals_job.cc b/chromium/storage/browser/blob/view_blob_internals_job.cc
index 1b5e91ef1c1..cf18d3e4f07 100644
--- a/chromium/storage/browser/blob/view_blob_internals_job.cc
+++ b/chromium/storage/browser/blob/view_blob_internals_job.cc
@@ -4,6 +4,9 @@
#include "storage/browser/blob/view_blob_internals_job.h"
+#include <stddef.h>
+#include <stdint.h>
+
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/format_macros.h"
@@ -223,17 +226,20 @@ void ViewBlobInternalsJob::GenerateHTMLForBlobData(
AddHTMLListItem(kType, "disk cache entry", out);
AddHTMLListItem(kURL, item.disk_cache_entry()->GetKey(), out);
break;
+ case DataElement::TYPE_BYTES_DESCRIPTION:
case DataElement::TYPE_UNKNOWN:
NOTREACHED();
break;
}
if (item.offset()) {
AddHTMLListItem(kOffset, base::UTF16ToUTF8(base::FormatNumber(
- static_cast<int64>(item.offset()))), out);
+ static_cast<int64_t>(item.offset()))),
+ out);
}
- if (static_cast<int64>(item.length()) != -1) {
+ if (static_cast<int64_t>(item.length()) != -1) {
AddHTMLListItem(kLength, base::UTF16ToUTF8(base::FormatNumber(
- static_cast<int64>(item.length()))), out);
+ static_cast<int64_t>(item.length()))),
+ out);
}
if (has_multi_items)
diff --git a/chromium/storage/browser/blob/view_blob_internals_job.h b/chromium/storage/browser/blob/view_blob_internals_job.h
index 6216dd32269..876df990da7 100644
--- a/chromium/storage/browser/blob/view_blob_internals_job.h
+++ b/chromium/storage/browser/blob/view_blob_internals_job.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "net/url_request/url_request_simple_job.h"
#include "storage/browser/storage_browser_export.h"