Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / content_hash_reader.cc
1 // 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/content_hash_reader.h"
6
7 #include "base/base64.h"
8 #include "base/file_util.h"
9 #include "base/json/json_reader.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/string_util.h"
12 #include "base/timer/elapsed_timer.h"
13 #include "base/values.h"
14 #include "crypto/sha2.h"
15 #include "extensions/browser/computed_hashes.h"
16 #include "extensions/browser/content_hash_tree.h"
17 #include "extensions/browser/verified_contents.h"
18 #include "extensions/common/extension.h"
19 #include "extensions/common/file_util.h"
20
21 using base::DictionaryValue;
22 using base::ListValue;
23 using base::Value;
24
25 namespace extensions {
26
27 ContentHashReader::ContentHashReader(const std::string& extension_id,
28                                      const base::Version& extension_version,
29                                      const base::FilePath& extension_root,
30                                      const base::FilePath& relative_path,
31                                      const ContentVerifierKey& key)
32     : extension_id_(extension_id),
33       extension_version_(extension_version.GetString()),
34       extension_root_(extension_root),
35       relative_path_(relative_path),
36       key_(key),
37       status_(NOT_INITIALIZED),
38       have_verified_contents_(false),
39       have_computed_hashes_(false),
40       block_size_(0) {
41 }
42
43 ContentHashReader::~ContentHashReader() {
44 }
45
46 bool ContentHashReader::Init() {
47   base::ElapsedTimer timer;
48   DCHECK_EQ(status_, NOT_INITIALIZED);
49   status_ = FAILURE;
50   base::FilePath verified_contents_path =
51       file_util::GetVerifiedContentsPath(extension_root_);
52
53   if (!base::PathExists(verified_contents_path))
54     return false;
55
56   verified_contents_.reset(new VerifiedContents(key_.data, key_.size));
57   if (!verified_contents_->InitFrom(verified_contents_path, false) ||
58       !verified_contents_->valid_signature() ||
59       !verified_contents_->version().Equals(extension_version_) ||
60       verified_contents_->extension_id() != extension_id_)
61     return false;
62
63   have_verified_contents_ = true;
64
65   base::FilePath computed_hashes_path =
66       file_util::GetComputedHashesPath(extension_root_);
67   if (!base::PathExists(computed_hashes_path))
68     return false;
69
70   ComputedHashes::Reader reader;
71   if (!reader.InitFromFile(computed_hashes_path))
72     return false;
73
74   have_computed_hashes_ = true;
75
76   if (!reader.GetHashes(relative_path_, &block_size_, &hashes_) ||
77       block_size_ % crypto::kSHA256Length != 0)
78     return false;
79
80   const std::string* expected_root =
81       verified_contents_->GetTreeHashRoot(relative_path_);
82   if (!expected_root)
83     return false;
84
85   std::string root =
86       ComputeTreeHashRoot(hashes_, block_size_ / crypto::kSHA256Length);
87   if (*expected_root != root)
88     return false;
89
90   status_ = SUCCESS;
91   UMA_HISTOGRAM_TIMES("ExtensionContentHashReader.InitLatency",
92                       timer.Elapsed());
93   return true;
94 }
95
96 int ContentHashReader::block_count() const {
97   DCHECK(status_ != NOT_INITIALIZED);
98   return hashes_.size();
99 }
100
101 int ContentHashReader::block_size() const {
102   DCHECK(status_ != NOT_INITIALIZED);
103   return block_size_;
104 }
105
106 bool ContentHashReader::GetHashForBlock(int block_index,
107                                         const std::string** result) const {
108   if (status_ != SUCCESS)
109     return false;
110   DCHECK(block_index >= 0);
111
112   if (static_cast<unsigned>(block_index) >= hashes_.size())
113     return false;
114   *result = &hashes_[block_index];
115
116   return true;
117 }
118
119 }  // namespace extensions