summaryrefslogtreecommitdiffstats
path: root/base/data_pack.cc
diff options
context:
space:
mode:
authorerg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-11 20:55:30 +0000
committererg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-11 20:55:30 +0000
commit5973945e4c3d2baf2b92d11be55c1692a09b12e3 (patch)
treee2abfada45cf20c85186c10e27c966c2cbc6bf55 /base/data_pack.cc
parent45c019ca34f3c9576ad1c3d24a885f97f1b80ba2 (diff)
downloadchromium_src-5973945e4c3d2baf2b92d11be55c1692a09b12e3.zip
chromium_src-5973945e4c3d2baf2b92d11be55c1692a09b12e3.tar.gz
chromium_src-5973945e4c3d2baf2b92d11be55c1692a09b12e3.tar.bz2
Completely redo how themes are stored on disk and processed at install time.
Rewrites most of BrowserThemeProvider and adds a new class BrowserThemePack. BrowserThemePack takes all the logic of generating resources out of the BrowserThemeProvider, does all of them at theme install time (previously, we lazily generated all the button images and a good number of colors, which muddled logic quite a bit), and then writes all the data out into an mmap()able file to speed startup when a theme is installed. In addition, this changes how the GtkThemeProvider works. The GtkThemeProvider now generates all of its images lazily and doesn't reach into the implementation details of BrowserThemeProvider as it used to. BUG=24493,21121 TEST=All the new unit tests pass. All the complex theme startup tests go faster. Review URL: http://codereview.chromium.org/460050 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34379 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/data_pack.cc')
-rw-r--r--base/data_pack.cc97
1 files changed, 84 insertions, 13 deletions
diff --git a/base/data_pack.cc b/base/data_pack.cc
index 27054d3..1078d0a 100644
--- a/base/data_pack.cc
+++ b/base/data_pack.cc
@@ -14,17 +14,22 @@
// http://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings
namespace {
-static const uint32_t kFileFormatVersion = 1;
+
+// A word is four bytes.
+static const size_t kWord = 4;
+
+static const uint32 kFileFormatVersion = 1;
// Length of file header: version and entry count.
-static const size_t kHeaderLength = 2 * sizeof(uint32_t);
+static const size_t kHeaderLength = 2 * sizeof(uint32);
+#pragma pack(push,1)
struct DataPackEntry {
- uint32_t resource_id;
- uint32_t file_offset;
- uint32_t length;
+ uint32 resource_id;
+ uint32 file_offset;
+ uint32 length;
static int CompareById(const void* void_key, const void* void_entry) {
- uint32_t key = *reinterpret_cast<const uint32_t*>(void_key);
+ uint32 key = *reinterpret_cast<const uint32*>(void_key);
const DataPackEntry* entry =
reinterpret_cast<const DataPackEntry*>(void_entry);
if (key < entry->resource_id) {
@@ -35,7 +40,10 @@ struct DataPackEntry {
return 0;
}
}
-} __attribute((packed));
+};
+#pragma pack(pop)
+
+COMPILE_ASSERT(sizeof(DataPackEntry) == 12, size_of_header_must_be_twelve);
} // anonymous namespace
@@ -50,12 +58,13 @@ DataPack::~DataPack() {
bool DataPack::Load(const FilePath& path) {
mmap_.reset(new file_util::MemoryMappedFile);
if (!mmap_->Initialize(path)) {
- PCHECK(false) << "Failed to mmap " << path.value();
+ DLOG(ERROR) << "Failed to mmap datapack";
+ return false;
}
// Parse the header of the file.
- // First uint32_t: version; second: resource count.
- const uint32* ptr = reinterpret_cast<const uint32_t*>(mmap_->data());
+ // First uint32: version; second: resource count.
+ const uint32* ptr = reinterpret_cast<const uint32*>(mmap_->data());
uint32 version = ptr[0];
if (version != kFileFormatVersion) {
LOG(ERROR) << "Bad data pack version: got " << version << ", expected "
@@ -89,7 +98,7 @@ bool DataPack::Load(const FilePath& path) {
return true;
}
-bool DataPack::GetStringPiece(uint32_t resource_id, StringPiece* data) {
+bool DataPack::GetStringPiece(uint32 resource_id, StringPiece* data) {
// It won't be hard to make this endian-agnostic, but it's not worth
// bothering to do right now.
#if defined(__BYTE_ORDER)
@@ -105,7 +114,6 @@ bool DataPack::GetStringPiece(uint32_t resource_id, StringPiece* data) {
bsearch(&resource_id, mmap_->data() + kHeaderLength, resource_count_,
sizeof(DataPackEntry), DataPackEntry::CompareById));
if (!target) {
- LOG(ERROR) << "No resource found with id: " << resource_id;
return false;
}
@@ -113,7 +121,7 @@ bool DataPack::GetStringPiece(uint32_t resource_id, StringPiece* data) {
return true;
}
-RefCountedStaticMemory* DataPack::GetStaticMemory(uint32_t resource_id) {
+RefCountedStaticMemory* DataPack::GetStaticMemory(uint32 resource_id) {
base::StringPiece piece;
if (!GetStringPiece(resource_id, &piece))
return NULL;
@@ -122,4 +130,67 @@ RefCountedStaticMemory* DataPack::GetStaticMemory(uint32_t resource_id) {
reinterpret_cast<const unsigned char*>(piece.data()), piece.length());
}
+// static
+bool DataPack::WritePack(const FilePath& path,
+ const std::map<uint32, StringPiece>& resources) {
+ FILE* file = file_util::OpenFile(path, "wb");
+ if (!file)
+ return false;
+
+ if (fwrite(&kFileFormatVersion, 1, kWord, file) != kWord) {
+ LOG(ERROR) << "Failed to write file version";
+ file_util::CloseFile(file);
+ return false;
+ }
+
+ // Note: the python version of this function explicitly sorted keys, but
+ // std::map is a sorted associative container, we shouldn't have to do that.
+ uint32 entry_count = resources.size();
+ if (fwrite(&entry_count, 1, kWord, file) != kWord) {
+ LOG(ERROR) << "Failed to write entry count";
+ file_util::CloseFile(file);
+ return false;
+ }
+
+ // Each entry is 3 uint32s.
+ uint32 index_length = entry_count * 3 * kWord;
+ uint32 data_offset = kHeaderLength + index_length;
+ for (std::map<uint32, StringPiece>::const_iterator it = resources.begin();
+ it != resources.end(); ++it) {
+ if (fwrite(&it->first, 1, kWord, file) != kWord) {
+ LOG(ERROR) << "Failed to write id for " << it->first;
+ file_util::CloseFile(file);
+ return false;
+ }
+
+ if (fwrite(&data_offset, 1, kWord, file) != kWord) {
+ LOG(ERROR) << "Failed to write offset for " << it->first;
+ file_util::CloseFile(file);
+ return false;
+ }
+
+ uint32 len = it->second.length();
+ if (fwrite(&len, 1, kWord, file) != kWord) {
+ LOG(ERROR) << "Failed to write length for " << it->first;
+ file_util::CloseFile(file);
+ return false;
+ }
+
+ data_offset += len;
+ }
+
+ for (std::map<uint32, StringPiece>::const_iterator it = resources.begin();
+ it != resources.end(); ++it) {
+ if (fwrite(it->second.data(), it->second.length(), 1, file) != 1) {
+ LOG(ERROR) << "Failed to write data for " << it->first;
+ file_util::CloseFile(file);
+ return false;
+ }
+ }
+
+ file_util::CloseFile(file);
+
+ return true;
+}
+
} // namespace base