Index: storage/browser/blob/blob_flattener.cc |
diff --git a/storage/browser/blob/blob_flattener.cc b/storage/browser/blob/blob_flattener.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..df1c5195c3faef5abdb805e061c682c8d115d5c4 |
--- /dev/null |
+++ b/storage/browser/blob/blob_flattener.cc |
@@ -0,0 +1,117 @@ |
+// Copyright 2016 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_flattener.h" |
+ |
+#include <limits> |
+#include <set> |
+#include <utility> |
+ |
+#include "storage/browser/blob/blob_async_transport_request_builder.h" |
+#include "storage/browser/blob/blob_data_builder.h" |
+#include "storage/browser/blob/blob_slice.h" |
+#include "storage/browser/blob/blob_storage_context.h" |
+#include "storage/browser/blob/blob_storage_registry.h" |
+#include "storage/browser/blob/shareable_blob_data_item.h" |
+ |
+namespace storage { |
+namespace { |
+using ItemCopyEntry = BlobStorageRegistry::ItemCopyEntry; |
+using BlobEntry = BlobStorageRegistry::Entry; |
+ |
+bool IsBytes(DataElement::Type type) { |
+ return type == DataElement::TYPE_BYTES || |
+ type == DataElement::TYPE_BYTES_DESCRIPTION; |
+} |
+ |
+} // namespace |
+ |
+// static |
+BlobFlattener::BlobFlattener(const BlobDataBuilder& transportation_result, |
+ InternalBlobData* output_blob, |
+ BlobStorageRegistry* registry) { |
+ const std::vector<scoped_refptr<BlobDataItem>>& transport_items = |
+ transportation_result.items_; |
+ const std::string& uuid = transportation_result.uuid_; |
+ |
+ std::set<std::string> dependent_blob_uuids; |
+ for (scoped_refptr<BlobDataItem> transport_item : transport_items) { |
+ DataElement::Type type = transport_item->type(); |
+ contains_pending_content |= type == DataElement::TYPE_BYTES_DESCRIPTION; |
+ |
+ if (IsBytes(type)) { |
+ memory_needed += transport_item->length(); |
+ total_size += transport_item->length(); |
+ output_blob->AppendSharedBlobItem( |
+ uuid, new ShareableBlobDataItem(std::move(transport_item))); |
kinuko
2016/07/17 16:15:46
if we continue here and the following 'else if' ca
dmurph
2016/07/19 02:26:27
Done.
|
+ } else if (type == DataElement::TYPE_BLOB) { |
+ BlobEntry* ref_entry = registry->GetEntry(transport_item->blob_uuid()); |
+ |
+ if (!ref_entry || BlobStatusIsError(ref_entry->status) || |
+ transport_item->blob_uuid() == uuid) { |
+ contains_broken_references = true; |
+ return; |
+ } |
+ |
+ if (dependent_blob_uuids.find(transport_item->blob_uuid()) == |
+ dependent_blob_uuids.end()) { |
+ dependent_blobs.push_back( |
+ std::make_pair(transport_item->blob_uuid(), ref_entry)); |
+ dependent_blob_uuids.insert(transport_item->blob_uuid()); |
+ } |
+ |
+ uint64_t length = transport_item->length() == DataElement::kUnknownSize |
+ ? ref_entry->data.total_size() |
+ : transport_item->length(); |
+ total_size += length; |
+ |
+ // If we're referencing the whole blob, then we don't need to slice. |
+ if (transport_item->offset() == 0 && |
+ length == ref_entry->data.total_size()) { |
+ for (const auto& shareable_item : ref_entry->data.items()) { |
+ output_blob->AppendSharedBlobItem(uuid, shareable_item); |
+ } |
+ continue; |
+ } |
+ |
+ // Validate our reference has good offset & length. |
+ if (transport_item->offset() + transport_item->length() > |
+ ref_entry->data.total_size()) { |
+ contains_invalid_references = true; |
+ return; |
+ } |
+ |
+ BlobSlice slice(ref_entry->data, transport_item->offset(), |
+ transport_item->length()); |
+ |
+ if (slice.first_source_item) { |
+ copies.push_back(ItemCopyEntry(slice.first_source_item, |
+ slice.first_item_slice_offset, |
+ slice.dest_items.front())); |
+ } |
+ if (slice.last_source_item) { |
+ copies.push_back( |
+ ItemCopyEntry(slice.last_source_item, 0, slice.dest_items.back())); |
+ } |
+ |
+ memory_needed += slice.copying_memory_size; |
+ for (auto& shareable_item : slice.dest_items) { |
+ output_blob->AppendSharedBlobItem(uuid, std::move(shareable_item)); |
+ } |
kinuko
2016/07/17 16:15:46
ditto, continue here and move out the following co
dmurph
2016/07/19 02:26:27
Done.
|
+ } else { |
+ if (type == DataElement::TYPE_FILE) { |
+ contains_pending_content |= |
+ transport_item->path().value() == |
+ BlobDataBuilder::kAppendFutureFileTemporaryFileName; |
+ } |
+ total_size += transport_item->length(); |
+ output_blob->AppendSharedBlobItem( |
+ uuid, new ShareableBlobDataItem(std::move(transport_item))); |
+ } |
+ } |
+} |
+ |
+BlobFlattener::~BlobFlattener() {} |
+ |
+} // namespace storage |