OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "modules/indexeddb/IDBValueUnwrapper.h" |
| 6 |
| 7 #include "bindings/core/v8/SerializationTag.h" |
| 8 #include "modules/indexeddb/IDBValue.h" |
| 9 #include "modules/indexeddb/IDBValueWrapper.h" |
| 10 #include "platform/blob/BlobData.h" |
| 11 #include "platform/wtf/text/WTFString.h" |
| 12 |
| 13 namespace blink { |
| 14 |
| 15 IDBValueUnwrapper::IDBValueUnwrapper() : data_(nullptr) {} |
| 16 |
| 17 bool IDBValueUnwrapper::IsWrapped(IDBValue* value) { |
| 18 uint8_t header[3]; |
| 19 value->data_->GetPartAsBytes(header, 0UL, sizeof(header)); |
| 20 return header[0] == kVersionTag && header[1] == 17 && header[2] == 1; |
| 21 } |
| 22 |
| 23 PassRefPtr<IDBValue> IDBValueUnwrapper::CreateUnwrapped( |
| 24 IDBValue* wrapped_value, |
| 25 PassRefPtr<SharedBuffer> unwrapped_data) { |
| 26 DCHECK_GT(wrapped_value->blob_info_->size(), 0U); |
| 27 DCHECK_EQ(wrapped_value->blob_info_->size(), |
| 28 wrapped_value->blob_data_->size()); |
| 29 |
| 30 // Create an IDBValue with the same blob information, minus the last blob. |
| 31 unsigned blob_count = wrapped_value->BlobInfo()->size() - 1; |
| 32 std::unique_ptr<Vector<RefPtr<BlobDataHandle>>> blob_data; |
| 33 blob_data->ReserveCapacity(blob_count); |
| 34 std::unique_ptr<Vector<WebBlobInfo>> blob_info; |
| 35 blob_info->ReserveCapacity(blob_count); |
| 36 |
| 37 for (unsigned i = 0; i < blob_count; ++i) { |
| 38 blob_data->push_back((*wrapped_value->blob_data_)[i]); |
| 39 blob_info->push_back((*wrapped_value->blob_info_)[i]); |
| 40 } |
| 41 |
| 42 return AdoptRef(new IDBValue(std::move(unwrapped_data), std::move(blob_data), |
| 43 std::move(blob_info))); |
| 44 } |
| 45 |
| 46 bool IDBValueUnwrapper::Parse(IDBValue* value) { |
| 47 #if DCHECK_IS_ON() |
| 48 blob_handle_.Clear(); |
| 49 #endif // DCHECK_IS_ON() |
| 50 |
| 51 // Fast path that avoids unnecessary dynamic allocations. |
| 52 if (!IDBValueUnwrapper::IsWrapped(value)) |
| 53 return false; |
| 54 |
| 55 data_ = reinterpret_cast<const uint8_t*>(value->data_->Data()); |
| 56 end_ = value->data_->size(); |
| 57 position_ = 0; |
| 58 |
| 59 String blob_uuid; |
| 60 if (!ReadVarint(blob_size_)) |
| 61 return false; |
| 62 if (!ReadAsciiString(blob_uuid)) |
| 63 return false; |
| 64 |
| 65 blob_handle_ = value->blob_data_->back(); |
| 66 if (blob_handle_->size() != blob_size_ || blob_handle_->Uuid() != blob_uuid) |
| 67 return false; |
| 68 |
| 69 #if DCHECK_IS_ON() |
| 70 data_ = nullptr; |
| 71 #endif // DCHECK_IS_ON() |
| 72 |
| 73 return true; |
| 74 } |
| 75 |
| 76 PassRefPtr<BlobDataHandle> IDBValueUnwrapper::WrapperBlobHandle() { |
| 77 DCHECK(blob_handle_); |
| 78 |
| 79 return std::move(blob_handle_); |
| 80 } |
| 81 |
| 82 bool IDBValueUnwrapper::ReadVarint(unsigned& value) { |
| 83 DCHECK(data_); |
| 84 |
| 85 value = 0; |
| 86 unsigned shift = 0; |
| 87 bool has_another_byte; |
| 88 do { |
| 89 if (position_ >= end_) |
| 90 return false; |
| 91 |
| 92 if (shift >= sizeof(unsigned) * 8) |
| 93 return false; |
| 94 value |= static_cast<unsigned>(data_[position_]) << shift; |
| 95 shift += 7; |
| 96 |
| 97 has_another_byte = value & 0x80; |
| 98 } while (has_another_byte); |
| 99 return true; |
| 100 } |
| 101 |
| 102 bool IDBValueUnwrapper::ReadAsciiString(String& value) { |
| 103 unsigned length; |
| 104 if (!ReadVarint(length)) |
| 105 return false; |
| 106 |
| 107 if (position_ + length > end_) |
| 108 return false; |
| 109 String output(data_ + position_, length); |
| 110 value.Swap(output); |
| 111 position_ += length; |
| 112 return true; |
| 113 } |
| 114 |
| 115 } // namespace blink |
OLD | NEW |