Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Side by Side Diff: chrome/browser/component_updater/component_unpacker.cc

Issue 15908002: Differential updates for components. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Sync to LKGR revision 207804. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/component_updater/component_unpacker.h" 5 #include "chrome/browser/component_updater/component_unpacker.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/json/json_file_value_serializer.h" 11 #include "base/json/json_file_value_serializer.h"
12 #include "base/memory/scoped_handle.h" 12 #include "base/memory/scoped_handle.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
15 #include "chrome/browser/component_updater/component_patcher.h"
15 #include "chrome/browser/component_updater/component_updater_service.h" 16 #include "chrome/browser/component_updater/component_updater_service.h"
16 #include "chrome/common/extensions/extension_constants.h" 17 #include "chrome/common/extensions/extension_constants.h"
17 #include "crypto/secure_hash.h" 18 #include "crypto/secure_hash.h"
18 #include "crypto/signature_verifier.h" 19 #include "crypto/signature_verifier.h"
19 #include "extensions/common/crx_file.h" 20 #include "extensions/common/crx_file.h"
20 #include "third_party/zlib/google/zip.h" 21 #include "third_party/zlib/google/zip.h"
21 22
22 using crypto::SecureHash; 23 using crypto::SecureHash;
23 24
24 namespace { 25 namespace {
26
25 // This class makes sure that the CRX digital signature is valid 27 // This class makes sure that the CRX digital signature is valid
26 // and well formed. 28 // and well formed.
27 class CRXValidator { 29 class CRXValidator {
28 public: 30 public:
29 explicit CRXValidator(FILE* crx_file) : valid_(false) { 31 explicit CRXValidator(FILE* crx_file) : valid_(false), delta_(false) {
30 extensions::CrxFile::Header header; 32 extensions::CrxFile::Header header;
31 size_t len = fread(&header, 1, sizeof(header), crx_file); 33 size_t len = fread(&header, 1, sizeof(header), crx_file);
32 if (len < sizeof(header)) 34 if (len < sizeof(header))
33 return; 35 return;
34 36
35 extensions::CrxFile::Error error; 37 extensions::CrxFile::Error error;
36 scoped_ptr<extensions::CrxFile> crx( 38 scoped_ptr<extensions::CrxFile> crx(
37 extensions::CrxFile::Parse(header, &error)); 39 extensions::CrxFile::Parse(header, &error));
38 if (!crx.get()) 40 if (!crx.get())
39 return; 41 return;
42 delta_ = extensions::CrxFile::HeaderIsDelta(header);
40 43
41 std::vector<uint8> key(header.key_size); 44 std::vector<uint8> key(header.key_size);
42 len = fread(&key[0], sizeof(uint8), header.key_size, crx_file); 45 len = fread(&key[0], sizeof(uint8), header.key_size, crx_file);
43 if (len < header.key_size) 46 if (len < header.key_size)
44 return; 47 return;
45 48
46 std::vector<uint8> signature(header.signature_size); 49 std::vector<uint8> signature(header.signature_size);
47 len = fread(&signature[0], sizeof(uint8), header.signature_size, crx_file); 50 len = fread(&signature[0], sizeof(uint8), header.signature_size, crx_file);
48 if (len < header.signature_size) 51 if (len < header.signature_size)
49 return; 52 return;
(...skipping 15 matching lines...) Expand all
65 68
66 if (!verifier.VerifyFinal()) 69 if (!verifier.VerifyFinal())
67 return; 70 return;
68 71
69 public_key_.swap(key); 72 public_key_.swap(key);
70 valid_ = true; 73 valid_ = true;
71 } 74 }
72 75
73 bool valid() const { return valid_; } 76 bool valid() const { return valid_; }
74 77
78 bool delta() const { return delta_; }
79
75 const std::vector<uint8>& public_key() const { return public_key_; } 80 const std::vector<uint8>& public_key() const { return public_key_; }
76 81
77 private: 82 private:
78 bool valid_; 83 bool valid_;
84 bool delta_;
79 std::vector<uint8> public_key_; 85 std::vector<uint8> public_key_;
80 }; 86 };
81 87
82 // Deserialize the CRX manifest. The top level must be a dictionary. 88 // Deserialize the CRX manifest. The top level must be a dictionary.
83 // TODO(cpu): add a specific attribute check to a component json that the 89 // TODO(cpu): add a specific attribute check to a component json that the
84 // extension unpacker will reject, so that a component cannot be installed 90 // extension unpacker will reject, so that a component cannot be installed
85 // as an extension. 91 // as an extension.
86 base::DictionaryValue* ReadManifest(const base::FilePath& unpack_path) { 92 base::DictionaryValue* ReadManifest(const base::FilePath& unpack_path) {
87 base::FilePath manifest = 93 base::FilePath manifest =
88 unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); 94 unpack_path.Append(FILE_PATH_LITERAL("manifest.json"));
89 if (!file_util::PathExists(manifest)) 95 if (!file_util::PathExists(manifest))
90 return NULL; 96 return NULL;
91 JSONFileValueSerializer serializer(manifest); 97 JSONFileValueSerializer serializer(manifest);
92 std::string error; 98 std::string error;
93 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error)); 99 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error));
94 if (!root.get()) 100 if (!root.get())
95 return NULL; 101 return NULL;
96 if (!root->IsType(base::Value::TYPE_DICTIONARY)) 102 if (!root->IsType(base::Value::TYPE_DICTIONARY))
97 return NULL; 103 return NULL;
98 return static_cast<base::DictionaryValue*>(root.release()); 104 return static_cast<base::DictionaryValue*>(root.release());
99 } 105 }
100 106
107 // Deletes a path if it exists, and then creates a directory there.
108 // Returns true if and only if these operations were successful.
109 // This method doesn't take any special steps to prevent files from
110 // being inserted into the target directory by another process or thread.
111 bool MakeEmptyDirectory(const base::FilePath& path) {
112 if (file_util::PathExists(path)) {
113 if (!file_util::Delete(path, true))
114 return false;
115 }
116 if (!file_util::CreateDirectory(path))
117 return false;
118 return true;
119 }
120
101 } // namespace. 121 } // namespace.
102 122
103 ComponentUnpacker::ComponentUnpacker(const std::vector<uint8>& pk_hash, 123 ComponentUnpacker::ComponentUnpacker(const std::vector<uint8>& pk_hash,
104 const base::FilePath& path, 124 const base::FilePath& path,
125 const std::string& fingerprint,
126 ComponentPatcher* patcher,
105 ComponentInstaller* installer) 127 ComponentInstaller* installer)
106 : error_(kNone) { 128 : error_(kNone),
129 extended_error_(0) {
107 if (pk_hash.empty() || path.empty()) { 130 if (pk_hash.empty() || path.empty()) {
108 error_ = kInvalidParams; 131 error_ = kInvalidParams;
109 return; 132 return;
110 } 133 }
111 // First, validate the CRX header and signature. As of today 134 // First, validate the CRX header and signature. As of today
112 // this is SHA1 with RSA 1024. 135 // this is SHA1 with RSA 1024.
113 ScopedStdioHandle file(file_util::OpenFile(path, "rb")); 136 ScopedStdioHandle file(file_util::OpenFile(path, "rb"));
114 if (!file.get()) { 137 if (!file.get()) {
115 error_ = kInvalidFile; 138 error_ = kInvalidFile;
116 return; 139 return;
(...skipping 11 matching lines...) Expand all
128 uint8 hash[32]; 151 uint8 hash[32];
129 scoped_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256)); 152 scoped_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256));
130 sha256->Update(&(validator.public_key()[0]), validator.public_key().size()); 153 sha256->Update(&(validator.public_key()[0]), validator.public_key().size());
131 sha256->Finish(hash, arraysize(hash)); 154 sha256->Finish(hash, arraysize(hash));
132 155
133 if (!std::equal(pk_hash.begin(), pk_hash.end(), hash)) { 156 if (!std::equal(pk_hash.begin(), pk_hash.end(), hash)) {
134 error_ = kInvalidId; 157 error_ = kInvalidId;
135 return; 158 return;
136 } 159 }
137 // We want the temporary directory to be unique and yet predictable, so 160 // We want the temporary directory to be unique and yet predictable, so
138 // we can easily find the package in a end user machine. 161 // we can easily find the package in an end user machine.
139 std::string dir( 162 const std::string dir(
140 base::StringPrintf("CRX_%s", base::HexEncode(hash, 6).c_str())); 163 base::StringPrintf("CRX_%s", base::HexEncode(hash, 6).c_str()));
141 unpack_path_ = path.DirName().AppendASCII(dir.c_str()); 164 unpack_path_ = path.DirName().AppendASCII(dir.c_str());
142 if (file_util::DirectoryExists(unpack_path_)) { 165 if (!MakeEmptyDirectory(unpack_path_)) {
143 if (!file_util::Delete(unpack_path_, true)) { 166 unpack_path_.clear();
144 unpack_path_.clear(); 167 error_ = kUnzipPathError;
145 error_ = kUzipPathError; 168 return;
169 }
170 if (validator.delta()) { // Package is a diff package.
171 // We want a different temp directory for the delta files; we'll put the
172 // patch output into unpack_path_.
173 std::string dir(
174 base::StringPrintf("CRX_%s_diff", base::HexEncode(hash, 6).c_str()));
175 base::FilePath unpack_diff_path = path.DirName().AppendASCII(dir.c_str());
176 if (!MakeEmptyDirectory(unpack_diff_path)) {
177 error_ = kUnzipPathError;
146 return; 178 return;
147 } 179 }
148 } 180 if (!zip::Unzip(path, unpack_diff_path)) {
149 if (!file_util::CreateDirectory(unpack_path_)) { 181 error_ = kUnzipFailed;
150 unpack_path_.clear(); 182 return;
151 error_ = kUzipPathError; 183 }
152 return; 184 ComponentUnpacker::Error result = DifferentialUpdatePatch(unpack_diff_path,
153 } 185 unpack_path_,
154 if (!zip::Unzip(path, unpack_path_)) { 186 patcher,
155 error_ = kUnzipFailed; 187 installer,
156 return; 188 &extended_error_);
189 file_util::Delete(unpack_diff_path, true);
190 unpack_diff_path.clear();
191 error_ = result;
192 if (error_ != kNone) {
193 return;
194 }
195 } else {
196 // Package is a normal update/install; unzip it into unpack_path_ directly.
197 if (!zip::Unzip(path, unpack_path_)) {
198 error_ = kUnzipFailed;
199 return;
200 }
157 } 201 }
158 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(unpack_path_)); 202 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(unpack_path_));
159 if (!manifest.get()) { 203 if (!manifest.get()) {
160 error_ = kBadManifest; 204 error_ = kBadManifest;
161 return; 205 return;
162 } 206 }
207 // Write the fingerprint to disk.
208 if (static_cast<int>(fingerprint.size()) !=
209 file_util::WriteFile(
210 unpack_path_.Append(FILE_PATH_LITERAL("manifest.fingerprint")),
211 fingerprint.c_str(),
212 fingerprint.size())) {
213 error_ = kFingerprintWriteFailed;
214 return;
215 }
163 if (!installer->Install(*manifest, unpack_path_)) { 216 if (!installer->Install(*manifest, unpack_path_)) {
164 error_ = kInstallerError; 217 error_ = kInstallerError;
165 return; 218 return;
166 } 219 }
167 // Installation successful. The directory is not our concern now. 220 // Installation successful. The directory is not our concern now.
168 unpack_path_.clear(); 221 unpack_path_.clear();
169 } 222 }
170 223
171 ComponentUnpacker::~ComponentUnpacker() { 224 ComponentUnpacker::~ComponentUnpacker() {
172 if (!unpack_path_.empty()) { 225 if (!unpack_path_.empty())
173 file_util::Delete(unpack_path_, true); 226 file_util::Delete(unpack_path_, true);
174 }
175 } 227 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698