Index: ui/base/resource/data_pack.cc |
diff --git a/ui/base/resource/data_pack.cc b/ui/base/resource/data_pack.cc |
index 544baf6c6e952cdda23f9fcb8812e63ef5164104..6de25681749a0bb68e2177e5405eeb6466b4c7bf 100644 |
--- a/ui/base/resource/data_pack.cc |
+++ b/ui/base/resource/data_pack.cc |
@@ -10,6 +10,7 @@ |
#include "base/files/file_util.h" |
#include "base/files/memory_mapped_file.h" |
#include "base/logging.h" |
+#include "base/memory/ptr_util.h" |
#include "base/memory/ref_counted_memory.h" |
#include "base/metrics/histogram_macros.h" |
#include "base/strings/string_piece.h" |
@@ -68,6 +69,52 @@ void LogDataPackError(LoadErrors error) { |
namespace ui { |
+// Abstraction of a data source (memory mapped file or in-memory buffer). |
+class DataPack::DataSource { |
+ public: |
+ virtual ~DataSource() {} |
+ |
+ virtual size_t GetLength() const = 0; |
+ virtual const uint8_t* GetData() const = 0; |
+}; |
+ |
+class DataPack::MemoryMappedDataSource : public DataPack::DataSource { |
+ public: |
+ explicit MemoryMappedDataSource(std::unique_ptr<base::MemoryMappedFile> mmap) |
+ : mmap_(std::move(mmap)) {} |
+ |
+ ~MemoryMappedDataSource() override {} |
+ |
+ // DataPack::DataSource: |
+ size_t GetLength() const override { return mmap_->length(); } |
+ |
+ const uint8_t* GetData() const override { return mmap_->data(); } |
+ |
+ private: |
+ std::unique_ptr<base::MemoryMappedFile> mmap_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MemoryMappedDataSource); |
+}; |
+ |
+class DataPack::BufferDataSource : public DataPack::DataSource { |
+ public: |
+ explicit BufferDataSource(base::StringPiece buffer) : buffer_(buffer) {} |
+ |
+ ~BufferDataSource() override {} |
+ |
+ // DataPack::DataSource: |
+ size_t GetLength() const override { return buffer_.length(); } |
+ |
+ const uint8_t* GetData() const override { |
+ return reinterpret_cast<const uint8_t*>(buffer_.data()); |
+ } |
+ |
+ private: |
+ base::StringPiece buffer_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(BufferDataSource); |
+}; |
+ |
DataPack::DataPack(ui::ScaleFactor scale_factor) |
: resource_count_(0), |
text_encoding_type_(BINARY), |
@@ -78,14 +125,15 @@ DataPack::~DataPack() { |
} |
bool DataPack::LoadFromPath(const base::FilePath& path) { |
- mmap_.reset(new base::MemoryMappedFile); |
- if (!mmap_->Initialize(path)) { |
+ std::unique_ptr<base::MemoryMappedFile> mmap = |
+ base::MakeUnique<base::MemoryMappedFile>(); |
+ if (!mmap->Initialize(path)) { |
DLOG(ERROR) << "Failed to mmap datapack"; |
LogDataPackError(INIT_FAILED); |
- mmap_.reset(); |
+ mmap.reset(); |
return false; |
} |
- return LoadImpl(); |
+ return LoadImpl(base::MakeUnique<MemoryMappedDataSource>(std::move(mmap))); |
} |
bool DataPack::LoadFromFile(base::File file) { |
@@ -96,34 +144,38 @@ bool DataPack::LoadFromFile(base::File file) { |
bool DataPack::LoadFromFileRegion( |
base::File file, |
const base::MemoryMappedFile::Region& region) { |
- mmap_.reset(new base::MemoryMappedFile); |
- if (!mmap_->Initialize(std::move(file), region)) { |
+ std::unique_ptr<base::MemoryMappedFile> mmap = |
+ base::MakeUnique<base::MemoryMappedFile>(); |
+ if (!mmap->Initialize(std::move(file), region)) { |
DLOG(ERROR) << "Failed to mmap datapack"; |
LogDataPackError(INIT_FAILED_FROM_FILE); |
- mmap_.reset(); |
+ mmap.reset(); |
return false; |
} |
- return LoadImpl(); |
+ return LoadImpl(base::MakeUnique<MemoryMappedDataSource>(std::move(mmap))); |
} |
-bool DataPack::LoadImpl() { |
+bool DataPack::LoadFromBuffer(base::StringPiece buffer) { |
+ return LoadImpl(base::MakeUnique<BufferDataSource>(buffer)); |
+} |
+ |
+bool DataPack::LoadImpl(std::unique_ptr<DataPack::DataSource> data_source) { |
// Sanity check the header of the file. |
- if (kHeaderLength > mmap_->length()) { |
+ if (kHeaderLength > data_source->GetLength()) { |
DLOG(ERROR) << "Data pack file corruption: incomplete file header."; |
LogDataPackError(HEADER_TRUNCATED); |
- mmap_.reset(); |
return false; |
} |
// Parse the header of the file. |
// First uint32_t: version; second: resource count; |
- const uint32_t* ptr = reinterpret_cast<const uint32_t*>(mmap_->data()); |
+ const uint32_t* ptr = |
+ reinterpret_cast<const uint32_t*>(data_source->GetData()); |
uint32_t version = ptr[0]; |
if (version != kFileFormatVersion) { |
LOG(ERROR) << "Bad data pack version: got " << version << ", expected " |
<< kFileFormatVersion; |
LogDataPackError(BAD_VERSION); |
- mmap_.reset(); |
return false; |
} |
resource_count_ = ptr[1]; |
@@ -136,7 +188,6 @@ bool DataPack::LoadImpl() { |
LOG(ERROR) << "Bad data pack text encoding: got " << text_encoding_type_ |
<< ", expected between " << BINARY << " and " << UTF16; |
LogDataPackError(WRONG_ENCODING); |
- mmap_.reset(); |
return false; |
} |
@@ -144,33 +195,34 @@ bool DataPack::LoadImpl() { |
// 1) Check we have enough entries. There's an extra entry after the last item |
// which gives the length of the last item. |
if (kHeaderLength + (resource_count_ + 1) * sizeof(DataPackEntry) > |
- mmap_->length()) { |
+ data_source->GetLength()) { |
LOG(ERROR) << "Data pack file corruption: too short for number of " |
"entries specified."; |
LogDataPackError(INDEX_TRUNCATED); |
- mmap_.reset(); |
return false; |
} |
// 2) Verify the entries are within the appropriate bounds. There's an extra |
// entry after the last item which gives us the length of the last item. |
for (size_t i = 0; i < resource_count_ + 1; ++i) { |
const DataPackEntry* entry = reinterpret_cast<const DataPackEntry*>( |
- mmap_->data() + kHeaderLength + (i * sizeof(DataPackEntry))); |
- if (entry->file_offset > mmap_->length()) { |
+ data_source->GetData() + kHeaderLength + (i * sizeof(DataPackEntry))); |
+ if (entry->file_offset > data_source->GetLength()) { |
LOG(ERROR) << "Entry #" << i << " in data pack points off end of file. " |
<< "Was the file corrupted?"; |
LogDataPackError(ENTRY_NOT_FOUND); |
- mmap_.reset(); |
return false; |
} |
} |
+ data_source_ = std::move(data_source); |
+ |
return true; |
} |
bool DataPack::HasResource(uint16_t resource_id) const { |
- return !!bsearch(&resource_id, mmap_->data() + kHeaderLength, resource_count_, |
- sizeof(DataPackEntry), DataPackEntry::CompareById); |
+ return !!bsearch(&resource_id, data_source_->GetData() + kHeaderLength, |
+ resource_count_, sizeof(DataPackEntry), |
+ DataPackEntry::CompareById); |
} |
bool DataPack::GetStringPiece(uint16_t resource_id, |
@@ -186,9 +238,9 @@ bool DataPack::GetStringPiece(uint16_t resource_id, |
#error DataPack assumes little endian |
#endif |
- const DataPackEntry* target = reinterpret_cast<const DataPackEntry*>( |
- bsearch(&resource_id, mmap_->data() + kHeaderLength, resource_count_, |
- sizeof(DataPackEntry), DataPackEntry::CompareById)); |
+ const DataPackEntry* target = reinterpret_cast<const DataPackEntry*>(bsearch( |
+ &resource_id, data_source_->GetData() + kHeaderLength, resource_count_, |
+ sizeof(DataPackEntry), DataPackEntry::CompareById)); |
if (!target) { |
return false; |
} |
@@ -197,9 +249,9 @@ bool DataPack::GetStringPiece(uint16_t resource_id, |
// If the next entry points beyond the end of the file this data pack's entry |
// table is corrupt. Log an error and return false. See |
// http://crbug.com/371301. |
- if (next_entry->file_offset > mmap_->length()) { |
- size_t entry_index = target - |
- reinterpret_cast<const DataPackEntry*>(mmap_->data() + kHeaderLength); |
+ if (next_entry->file_offset > data_source_->GetLength()) { |
+ size_t entry_index = target - reinterpret_cast<const DataPackEntry*>( |
+ data_source_->GetData() + kHeaderLength); |
LOG(ERROR) << "Entry #" << entry_index << " in data pack points off end " |
<< "of file. This should have been caught when loading. Was the " |
<< "file modified?"; |
@@ -207,7 +259,8 @@ bool DataPack::GetStringPiece(uint16_t resource_id, |
} |
size_t length = next_entry->file_offset - target->file_offset; |
- data->set(reinterpret_cast<const char*>(mmap_->data() + target->file_offset), |
+ data->set(reinterpret_cast<const char*>(data_source_->GetData() + |
+ target->file_offset), |
length); |
return true; |
} |
@@ -234,7 +287,7 @@ void DataPack::CheckForDuplicateResources( |
const ScopedVector<ResourceHandle>& packs) { |
for (size_t i = 0; i < resource_count_ + 1; ++i) { |
const DataPackEntry* entry = reinterpret_cast<const DataPackEntry*>( |
- mmap_->data() + kHeaderLength + (i * sizeof(DataPackEntry))); |
+ data_source_->GetData() + kHeaderLength + (i * sizeof(DataPackEntry))); |
const uint16_t resource_id = entry->resource_id; |
const float resource_scale = GetScaleForScaleFactor(scale_factor_); |
for (const ResourceHandle* handle : packs) { |