Index: third_party/WebKit/Source/modules/indexeddb/IDBValueUnwrapper.cpp |
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBValueUnwrapper.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBValueUnwrapper.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..76a97ecf19238575baf1cfc787bf5d63caac0196 |
--- /dev/null |
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBValueUnwrapper.cpp |
@@ -0,0 +1,115 @@ |
+// Copyright 2017 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 "modules/indexeddb/IDBValueUnwrapper.h" |
+ |
+#include "bindings/core/v8/SerializationTag.h" |
+#include "modules/indexeddb/IDBValue.h" |
+#include "modules/indexeddb/IDBValueWrapper.h" |
+#include "platform/blob/BlobData.h" |
+#include "platform/wtf/text/WTFString.h" |
+ |
+namespace blink { |
+ |
+IDBValueUnwrapper::IDBValueUnwrapper() : data_(nullptr) {} |
+ |
+bool IDBValueUnwrapper::IsWrapped(IDBValue* value) { |
+ uint8_t header[3]; |
+ value->data_->GetPartAsBytes(header, 0UL, sizeof(header)); |
+ return header[0] == kVersionTag && header[1] == 17 && header[2] == 1; |
+} |
+ |
+PassRefPtr<IDBValue> IDBValueUnwrapper::CreateUnwrapped( |
+ IDBValue* wrapped_value, |
+ PassRefPtr<SharedBuffer> unwrapped_data) { |
+ DCHECK_GT(wrapped_value->blob_info_->size(), 0U); |
+ DCHECK_EQ(wrapped_value->blob_info_->size(), |
+ wrapped_value->blob_data_->size()); |
+ |
+ // Create an IDBValue with the same blob information, minus the last blob. |
+ unsigned blob_count = wrapped_value->BlobInfo()->size() - 1; |
+ std::unique_ptr<Vector<RefPtr<BlobDataHandle>>> blob_data; |
+ blob_data->ReserveCapacity(blob_count); |
+ std::unique_ptr<Vector<WebBlobInfo>> blob_info; |
+ blob_info->ReserveCapacity(blob_count); |
+ |
+ for (unsigned i = 0; i < blob_count; ++i) { |
+ blob_data->push_back((*wrapped_value->blob_data_)[i]); |
+ blob_info->push_back((*wrapped_value->blob_info_)[i]); |
+ } |
+ |
+ return AdoptRef(new IDBValue(std::move(unwrapped_data), std::move(blob_data), |
+ std::move(blob_info))); |
+} |
+ |
+bool IDBValueUnwrapper::Parse(IDBValue* value) { |
+#if DCHECK_IS_ON() |
+ blob_handle_.Clear(); |
+#endif // DCHECK_IS_ON() |
+ |
+ // Fast path that avoids unnecessary dynamic allocations. |
+ if (!IDBValueUnwrapper::IsWrapped(value)) |
+ return false; |
+ |
+ data_ = reinterpret_cast<const uint8_t*>(value->data_->Data()); |
+ end_ = value->data_->size(); |
+ position_ = 0; |
+ |
+ String blob_uuid; |
+ if (!ReadVarint(blob_size_)) |
+ return false; |
+ if (!ReadAsciiString(blob_uuid)) |
+ return false; |
+ |
+ blob_handle_ = value->blob_data_->back(); |
+ if (blob_handle_->size() != blob_size_ || blob_handle_->Uuid() != blob_uuid) |
+ return false; |
+ |
+#if DCHECK_IS_ON() |
+ data_ = nullptr; |
+#endif // DCHECK_IS_ON() |
+ |
+ return true; |
+} |
+ |
+PassRefPtr<BlobDataHandle> IDBValueUnwrapper::WrapperBlobHandle() { |
+ DCHECK(blob_handle_); |
+ |
+ return std::move(blob_handle_); |
+} |
+ |
+bool IDBValueUnwrapper::ReadVarint(unsigned& value) { |
+ DCHECK(data_); |
+ |
+ value = 0; |
+ unsigned shift = 0; |
+ bool has_another_byte; |
+ do { |
+ if (position_ >= end_) |
+ return false; |
+ |
+ if (shift >= sizeof(unsigned) * 8) |
+ return false; |
+ value |= static_cast<unsigned>(data_[position_]) << shift; |
+ shift += 7; |
+ |
+ has_another_byte = value & 0x80; |
+ } while (has_another_byte); |
+ return true; |
+} |
+ |
+bool IDBValueUnwrapper::ReadAsciiString(String& value) { |
+ unsigned length; |
+ if (!ReadVarint(length)) |
+ return false; |
+ |
+ if (position_ + length > end_) |
+ return false; |
+ String output(data_ + position_, length); |
+ value.Swap(output); |
+ position_ += length; |
+ return true; |
+} |
+ |
+} // namespace blink |