blob: a4eb9565c8ec517c3e3cb47b628646bf1b9778c3 [file] [log] [blame]
[email protected]abd4cb22014-05-16 05:22:561// Copyright 2014 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 "extensions/browser/computed_hashes.h"
6
7#include "base/base64.h"
8#include "base/file_util.h"
9#include "base/files/file_path.h"
10#include "base/json/json_reader.h"
11#include "base/json/json_writer.h"
12
13namespace {
14const char kPathKey[] = "path";
15const char kBlockSizeKey[] = "block_size";
16const char kBlockHashesKey[] = "block_hashes";
17}
18
19namespace extensions {
20
21ComputedHashes::Reader::Reader() {
22}
23ComputedHashes::Reader::~Reader() {
24}
25
26bool ComputedHashes::Reader::InitFromFile(const base::FilePath& path) {
27 std::string contents;
28 if (!base::ReadFileToString(path, &contents))
29 return false;
30
31 base::ListValue* all_hashes = NULL;
32 scoped_ptr<base::Value> value(base::JSONReader::Read(contents));
33 if (!value.get() || !value->GetAsList(&all_hashes))
34 return false;
35
36 for (size_t i = 0; i < all_hashes->GetSize(); i++) {
37 base::DictionaryValue* dictionary = NULL;
38 if (!all_hashes->GetDictionary(i, &dictionary))
39 return false;
40
41 std::string relative_path_utf8;
42 if (!dictionary->GetString(kPathKey, &relative_path_utf8))
43 return false;
44
45 int block_size;
46 if (!dictionary->GetInteger(kBlockSizeKey, &block_size))
47 return false;
48 if (block_size <= 0 || ((block_size % 1024) != 0)) {
49 LOG(ERROR) << "Invalid block size: " << block_size;
50 block_size = 0;
51 return false;
52 }
53
54 base::ListValue* hashes_list = NULL;
55 if (!dictionary->GetList(kBlockHashesKey, &hashes_list))
56 return false;
57
58 base::FilePath relative_path =
59 base::FilePath::FromUTF8Unsafe(relative_path_utf8);
[email protected]4f9bdf62014-06-28 01:08:2260 relative_path = relative_path.NormalizePathSeparatorsTo('/');
[email protected]abd4cb22014-05-16 05:22:5661
62 data_[relative_path] = HashInfo(block_size, std::vector<std::string>());
63 std::vector<std::string>* hashes = &(data_[relative_path].second);
64
65 for (size_t j = 0; j < hashes_list->GetSize(); j++) {
66 std::string encoded;
67 if (!hashes_list->GetString(j, &encoded))
68 return false;
69
70 hashes->push_back(std::string());
71 std::string* decoded = &hashes->back();
72 if (!base::Base64Decode(encoded, decoded)) {
73 hashes->clear();
74 return false;
75 }
76 }
77 }
78 return true;
79}
80
81bool ComputedHashes::Reader::GetHashes(const base::FilePath& relative_path,
82 int* block_size,
83 std::vector<std::string>* hashes) {
[email protected]4f9bdf62014-06-28 01:08:2284 base::FilePath path = relative_path.NormalizePathSeparatorsTo('/');
85 std::map<base::FilePath, HashInfo>::iterator i = data_.find(path);
[email protected]abd4cb22014-05-16 05:22:5686 if (i == data_.end())
87 return false;
88 HashInfo& info = i->second;
89 *block_size = info.first;
90 *hashes = info.second;
91 return true;
92}
93
94ComputedHashes::Writer::Writer() {
95}
96ComputedHashes::Writer::~Writer() {
97}
98
99void ComputedHashes::Writer::AddHashes(const base::FilePath& relative_path,
100 int block_size,
101 const std::vector<std::string>& hashes) {
102 base::DictionaryValue* dict = new base::DictionaryValue();
103 base::ListValue* block_hashes = new base::ListValue();
104 file_list_.Append(dict);
[email protected]4f9bdf62014-06-28 01:08:22105 dict->SetString(kPathKey,
106 relative_path.NormalizePathSeparatorsTo('/').AsUTF8Unsafe());
[email protected]abd4cb22014-05-16 05:22:56107 dict->SetInteger(kBlockSizeKey, block_size);
108 dict->Set(kBlockHashesKey, block_hashes);
109
110 for (std::vector<std::string>::const_iterator i = hashes.begin();
111 i != hashes.end();
112 ++i) {
113 std::string encoded;
114 base::Base64Encode(*i, &encoded);
115 block_hashes->AppendString(encoded);
116 }
117}
118
119bool ComputedHashes::Writer::WriteToFile(const base::FilePath& path) {
120 std::string json;
121 if (!base::JSONWriter::Write(&file_list_, &json))
122 return false;
123 int written = base::WriteFile(path, json.data(), json.size());
124 if (static_cast<unsigned>(written) != json.size()) {
125 LOG(ERROR) << "Error writing " << path.MaybeAsASCII()
126 << " ; write result:" << written << " expected:" << json.size();
127 return false;
128 }
129 return true;
130}
131
132} // namespace extensions