Preliminary interactive layout of window manager's demo_launcher.
[chromium-blink-merge.git] / tools / ipc_fuzzer / message_lib / message_file_writer.cc
blob2554b12f513624c1a6ed36245cd97f0998e65fb4
1 // Copyright 2013 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.
5 #include <limits.h>
6 #include <set>
8 #include "base/files/file.h"
9 #include "base/logging.h"
10 #include "tools/ipc_fuzzer/message_lib/message_file.h"
11 #include "tools/ipc_fuzzer/message_lib/message_file_format.h"
12 #include "tools/ipc_fuzzer/message_lib/message_names.h"
14 namespace ipc_fuzzer {
16 namespace {
18 // Helper class to write a MessageVector + message names to a file.
19 class Writer {
20 public:
21 Writer(const base::FilePath& path);
22 ~Writer() {}
23 bool Write(const MessageVector& messages);
25 private:
26 bool OpenFile();
28 // Helper to append data to file_.
29 bool WriteBlob(const void *buffer, size_t size);
31 // Collects a set of MessageVector message types. Corresponding message
32 // names need to be included in the file.
33 bool CollectMessageTypes();
35 bool WriteHeader();
36 bool WriteMessages();
38 // Each name table entry is a message type + string table offset.
39 bool WriteNameTable();
41 // String table contains the actual message names.
42 bool WriteStringTable();
44 typedef std::set<uint32> TypesSet;
45 base::FilePath path_;
46 base::File file_;
47 const MessageVector* messages_;
48 TypesSet types_;
50 DISALLOW_COPY_AND_ASSIGN(Writer);
53 Writer::Writer(const base::FilePath& path) : path_(path), messages_(NULL) {
56 bool Writer::OpenFile() {
57 file_.Initialize(path_,
58 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
59 if (!file_.IsValid()) {
60 LOG(ERROR) << "Failed to create IPC message file: " << path_.value();
61 return false;
63 return true;
66 bool Writer::WriteBlob(const void *buffer, size_t size) {
67 if (size > INT_MAX)
68 return false;
69 const char* char_buffer = static_cast<const char*>(buffer);
70 int ret = file_.WriteAtCurrentPos(char_buffer, size);
71 if (ret != static_cast<int>(size)) {
72 LOG(ERROR) << "Failed to write " << size << " bytes.";
73 return false;
75 return true;
78 bool Writer::CollectMessageTypes() {
79 for (size_t i = 0; i < messages_->size(); ++i) {
80 uint32_t type = (*messages_)[i]->type();
81 if (!MessageNames::GetInstance()->TypeExists(type)) {
82 LOG(ERROR) << "Unknown message type: " << type;
83 return false;
85 types_.insert(type);
87 return true;
90 bool Writer::WriteHeader() {
91 FileHeader header;
92 if (messages_->size() > UINT_MAX)
93 return false;
94 header.magic = FileHeader::kMagicValue;
95 header.version = FileHeader::kCurrentVersion;
96 header.message_count = messages_->size();
97 header.name_count = types_.size();
98 if (!WriteBlob(&header, sizeof(FileHeader)))
99 return false;
100 return true;
103 bool Writer::WriteMessages() {
104 for (size_t i = 0; i < messages_->size(); ++i) {
105 IPC::Message* message = (*messages_)[i];
106 if (!WriteBlob(message->data(), message->size()))
107 return false;
109 return true;
112 bool Writer::WriteNameTable() {
113 size_t string_table_offset = 0;
114 NameTableEntry entry;
116 for (TypesSet::iterator it = types_.begin(); it != types_.end(); ++it) {
117 if (string_table_offset > UINT_MAX)
118 return false;
119 entry.type = *it;
120 entry.string_table_offset = string_table_offset;
121 if (!WriteBlob(&entry, sizeof(NameTableEntry)))
122 return false;
123 const std::string& name = MessageNames::GetInstance()->TypeToName(*it);
124 string_table_offset += name.length() + 1;
126 return true;
129 bool Writer::WriteStringTable() {
130 for (TypesSet::iterator it = types_.begin(); it != types_.end(); ++it) {
131 const std::string& name = MessageNames::GetInstance()->TypeToName(*it);
132 if (!WriteBlob(name.c_str(), name.length() + 1))
133 return false;
135 return true;
138 bool Writer::Write(const MessageVector& messages) {
139 messages_ = &messages;
141 if (!OpenFile())
142 return false;
143 if (!CollectMessageTypes())
144 return false;
145 if (!WriteHeader())
146 return false;
147 if (!WriteMessages())
148 return false;
149 if (!WriteNameTable())
150 return false;
151 if (!WriteStringTable())
152 return false;
154 return true;
157 } // namespace
159 bool MessageFile::Write(const base::FilePath& path,
160 const MessageVector& messages) {
161 Writer writer(path);
162 return writer.Write(messages);
165 } // namespace ipc_fuzzer