Upstream version 10.38.220.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       content_exists_(false),
39       have_verified_contents_(false),
40       have_computed_hashes_(false),
41       block_size_(0) {
42 }
43
44 ContentHashReader::~ContentHashReader() {
45 }
46
47 bool ContentHashReader::Init() {
48   base::ElapsedTimer timer;
49   DCHECK_EQ(status_, NOT_INITIALIZED);
50   status_ = FAILURE;
51   base::FilePath verified_contents_path =
52       file_util::GetVerifiedContentsPath(extension_root_);
53
54   // Check that this is a valid resource to verify (i.e., it exists).
55   base::FilePath content_path = extension_root_.Append(relative_path_);
56   if (!base::PathExists(content_path))
57     return false;
58
59   content_exists_ = true;
60
61   if (!base::PathExists(verified_contents_path))
62     return false;
63
64   verified_contents_.reset(new VerifiedContents(key_.data, key_.size));
65   if (!verified_contents_->InitFrom(verified_contents_path, false) ||
66       !verified_contents_->valid_signature() ||
67       !verified_contents_->version().Equals(extension_version_) ||
68       verified_contents_->extension_id() != extension_id_)
69     return false;
70
71   have_verified_contents_ = true;
72
73   base::FilePath computed_hashes_path =
74       file_util::GetComputedHashesPath(extension_root_);
75   if (!base::PathExists(computed_hashes_path))
76     return false;
77
78   ComputedHashes::Reader reader;
79   if (!reader.InitFromFile(computed_hashes_path))
80     return false;
81
82   have_computed_hashes_ = true;
83
84   if (!reader.GetHashes(relative_path_, &block_size_, &hashes_) ||
85       block_size_ % crypto::kSHA256Length != 0)
86     return false;
87
88   std::string root =
89       ComputeTreeHashRoot(hashes_, block_size_ / crypto::kSHA256Length);
90   if (!verified_contents_->TreeHashRootEquals(relative_path_, root))
91     return false;
92
93   status_ = SUCCESS;
94   UMA_HISTOGRAM_TIMES("ExtensionContentHashReader.InitLatency",
95                       timer.Elapsed());
96   return true;
97 }
98
99 int ContentHashReader::block_count() const {
100   DCHECK(status_ != NOT_INITIALIZED);
101   return hashes_.size();
102 }
103
104 int ContentHashReader::block_size() const {
105   DCHECK(status_ != NOT_INITIALIZED);
106   return block_size_;
107 }
108
109 bool ContentHashReader::GetHashForBlock(int block_index,
110                                         const std::string** result) const {
111   if (status_ != SUCCESS)
112     return false;
113   DCHECK(block_index >= 0);
114
115   if (static_cast<unsigned>(block_index) >= hashes_.size())
116     return false;
117   *result = &hashes_[block_index];
118
119   return true;
120 }
121
122 }  // namespace extensions