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

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

Issue 321473003: Elevated install of recovery component (component update part) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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/bind.h" 10 #include "base/bind.h"
(...skipping 13 matching lines...) Expand all
24 #include "extensions/common/constants.h" 24 #include "extensions/common/constants.h"
25 #include "extensions/common/crx_file.h" 25 #include "extensions/common/crx_file.h"
26 #include "third_party/zlib/google/zip.h" 26 #include "third_party/zlib/google/zip.h"
27 27
28 using crypto::SecureHash; 28 using crypto::SecureHash;
29 29
30 namespace component_updater { 30 namespace component_updater {
31 31
32 namespace { 32 namespace {
33 33
34 namespace serialize {
35
36 const char kKeyFingerprint[] = "fingerprint";
37 const char kKeyPKHash[] = "public_key_hash";
38 const char kKeyInProcess[] = "in_process";
39
40 const base::FilePath::CharType kCrxFileName[] =
41 FILE_PATH_LITERAL("saved_installer.crx");
42 const base::FilePath::CharType kInstallDataFileName[] =
43 FILE_PATH_LITERAL("metadata.json");
44
45 } // namespace serialize
46
34 // This class makes sure that the CRX digital signature is valid 47 // This class makes sure that the CRX digital signature is valid
35 // and well formed. 48 // and well formed.
36 class CRXValidator { 49 class CRXValidator {
37 public: 50 public:
38 explicit CRXValidator(FILE* crx_file) : valid_(false), is_delta_(false) { 51 explicit CRXValidator(FILE* crx_file) : valid_(false), is_delta_(false) {
39 extensions::CrxFile::Header header; 52 extensions::CrxFile::Header header;
40 size_t len = fread(&header, 1, sizeof(header), crx_file); 53 size_t len = fread(&header, 1, sizeof(header), crx_file);
41 if (len < sizeof(header)) 54 if (len < sizeof(header))
42 return; 55 return;
43 56
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 // TODO(cpu): add a specific attribute check to a component json that the 130 // TODO(cpu): add a specific attribute check to a component json that the
118 // extension unpacker will reject, so that a component cannot be installed 131 // extension unpacker will reject, so that a component cannot be installed
119 // as an extension. 132 // as an extension.
120 scoped_ptr<base::DictionaryValue> ReadManifest( 133 scoped_ptr<base::DictionaryValue> ReadManifest(
121 const base::FilePath& unpack_path) { 134 const base::FilePath& unpack_path) {
122 base::FilePath manifest = 135 base::FilePath manifest =
123 unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); 136 unpack_path.Append(FILE_PATH_LITERAL("manifest.json"));
124 if (!base::PathExists(manifest)) 137 if (!base::PathExists(manifest))
125 return scoped_ptr<base::DictionaryValue>(); 138 return scoped_ptr<base::DictionaryValue>();
126 JSONFileValueSerializer serializer(manifest); 139 JSONFileValueSerializer serializer(manifest);
127 std::string error; 140 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, NULL));
128 scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error));
129 if (!root.get()) 141 if (!root.get())
130 return scoped_ptr<base::DictionaryValue>(); 142 return scoped_ptr<base::DictionaryValue>();
131 if (!root->IsType(base::Value::TYPE_DICTIONARY)) 143 if (!root->IsType(base::Value::TYPE_DICTIONARY))
132 return scoped_ptr<base::DictionaryValue>(); 144 return scoped_ptr<base::DictionaryValue>();
133 return scoped_ptr<base::DictionaryValue>( 145 return scoped_ptr<base::DictionaryValue>(
134 static_cast<base::DictionaryValue*>(root.release())).Pass(); 146 static_cast<base::DictionaryValue*>(root.release())).Pass();
135 } 147 }
136 148
137 bool ComponentUnpacker::UnpackInternal() { 149 bool ComponentUnpacker::UnpackInternal() {
138 return Verify() && Unzip() && BeginPatching(); 150 return Verify() && Unzip() && BeginPatching();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 187
176 if (!std::equal(pk_hash_.begin(), pk_hash_.end(), hash)) { 188 if (!std::equal(pk_hash_.begin(), pk_hash_.end(), hash)) {
177 VLOG(1) << "Hash mismatch: " << path_.value(); 189 VLOG(1) << "Hash mismatch: " << path_.value();
178 error_ = kInvalidId; 190 error_ = kInvalidId;
179 return false; 191 return false;
180 } 192 }
181 VLOG(1) << "Verification successful: " << path_.value(); 193 VLOG(1) << "Verification successful: " << path_.value();
182 return true; 194 return true;
183 } 195 }
184 196
197 bool ComponentUnpacker::CreateUnpackDirectory(base::FilePath* new_dir) {
198 if (unpack_base_dir_.empty()) {
199 return base::CreateNewTempDirectory(base::FilePath::StringType(), new_dir);
200 }
201
202 return base::CreateTemporaryDirInDir(
203 unpack_base_dir_, base::FilePath::StringType(), new_dir);
204 }
205
185 bool ComponentUnpacker::Unzip() { 206 bool ComponentUnpacker::Unzip() {
186 base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_; 207 base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_;
187 VLOG(1) << "Unpacking in: " << destination.value(); 208 VLOG(1) << "Unpacking in: " << destination.value();
188 if (!base::CreateNewTempDirectory(base::FilePath::StringType(), 209 if (!CreateUnpackDirectory(&destination)) {
189 &destination)) {
190 VLOG(1) << "Unable to create temporary directory for unpacking."; 210 VLOG(1) << "Unable to create temporary directory for unpacking.";
191 error_ = kUnzipPathError; 211 error_ = kUnzipPathError;
192 return false; 212 return false;
193 } 213 }
194 if (!zip::Unzip(path_, destination)) { 214 if (!zip::Unzip(path_, destination)) {
195 VLOG(1) << "Unzipping failed."; 215 VLOG(1) << "Unzipping failed.";
196 error_ = kUnzipFailed; 216 error_ = kUnzipFailed;
197 return false; 217 return false;
198 } 218 }
199 VLOG(1) << "Unpacked successfully"; 219 VLOG(1) << "Unpacked successfully";
200 return true; 220 return true;
201 } 221 }
202 222
203 bool ComponentUnpacker::BeginPatching() { 223 bool ComponentUnpacker::BeginPatching() {
204 if (is_delta_) { // Package is a diff package. 224 if (is_delta_) { // Package is a diff package.
205 // Use a different temp directory for the patch output files. 225 // Use a different temp directory for the patch output files.
206 if (!base::CreateNewTempDirectory(base::FilePath::StringType(), 226 if (!CreateUnpackDirectory(&unpack_path_)) {
207 &unpack_path_)) {
208 error_ = kUnzipPathError; 227 error_ = kUnzipPathError;
209 return false; 228 return false;
210 } 229 }
211 patcher_ = new ComponentPatcher(unpack_diff_path_, 230 patcher_ = new ComponentPatcher(unpack_diff_path_,
212 unpack_path_, 231 unpack_path_,
213 installer_, 232 installer_,
214 in_process_, 233 in_process_,
215 task_runner_); 234 task_runner_);
216 task_runner_->PostTask( 235 task_runner_->PostTask(
217 FROM_HERE, 236 FROM_HERE,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 error_ = kFingerprintWriteFailed; 276 error_ = kFingerprintWriteFailed;
258 return; 277 return;
259 } 278 }
260 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(unpack_path_)); 279 scoped_ptr<base::DictionaryValue> manifest(ReadManifest(unpack_path_));
261 if (!manifest.get()) { 280 if (!manifest.get()) {
262 error_ = kBadManifest; 281 error_ = kBadManifest;
263 return; 282 return;
264 } 283 }
265 DCHECK(error_ == kNone); 284 DCHECK(error_ == kNone);
266 if (!installer_->Install(*manifest, unpack_path_)) { 285 if (!installer_->Install(*manifest, unpack_path_)) {
286 // Saves the installer files and tries to re-install which is not managed
287 // by the component updater service.
288 if (SaveInstallSource(installer_->GetBackupPath())) {
289 installer_->InstallExternally();
290 }
291
292 // But keep current install error code since we cannot get the external
293 // install result.
267 error_ = kInstallerError; 294 error_ = kInstallerError;
268 return; 295 return;
269 } 296 }
270 } 297 }
271 298
272 void ComponentUnpacker::Finish() { 299 void ComponentUnpacker::Finish() {
273 if (!unpack_diff_path_.empty()) 300 if (!unpack_diff_path_.empty())
274 base::DeleteFile(unpack_diff_path_, true); 301 base::DeleteFile(unpack_diff_path_, true);
275 if (!unpack_path_.empty()) 302 if (!unpack_path_.empty())
276 base::DeleteFile(unpack_path_, true); 303 base::DeleteFile(unpack_path_, true);
277 callback_.Run(error_, extended_error_); 304 callback_.Run(error_, extended_error_);
278 } 305 }
279 306
280 ComponentUnpacker::~ComponentUnpacker() { 307 ComponentUnpacker::~ComponentUnpacker() {
281 } 308 }
282 309
310 bool ComponentUnpacker::SaveInstallSource(
311 const base::FilePath& backup_path) const {
312 if (backup_path.empty()) {
313 return false;
314 }
315
316 if (!base::CreateDirectory(backup_path)) {
317 return false;
318 }
319
320 const base::FilePath crx_path = backup_path.Append(serialize::kCrxFileName);
321 if (!base::CopyFile(path_, crx_path)) {
322 return false;
323 }
324
325 const base::FilePath install_data_file_path =
326 backup_path.Append(serialize::kInstallDataFileName);
327 JSONFileValueSerializer serializer(install_data_file_path);
328
329 scoped_ptr<base::DictionaryValue> root(new base::DictionaryValue);
330 root->SetString(serialize::kKeyFingerprint, fingerprint_);
331 root->SetBoolean(serialize::kKeyInProcess, in_process_);
332 scoped_ptr<base::ListValue> pk_hash_list(new base::ListValue);
333 for (size_t i = 0; i < pk_hash_.size(); ++i) {
334 pk_hash_list->Append(base::Value::CreateIntegerValue(
335 static_cast<int>(pk_hash_[i])));
336 }
337 root->Set(serialize::kKeyPKHash, pk_hash_list.release());
338 if (!serializer.Serialize(*root)) {
339 return false;
340 }
341
342 return true;
343 }
344
345 void ComponentUnpacker::set_unpack_base_dir(const base::FilePath& path) {
346 unpack_base_dir_ = path;
347 }
348
349 scoped_refptr<ComponentUnpacker> ComponentUnpacker::CreateFromBackup(
350 const base::FilePath& backup_path,
351 const std::vector<uint8>& pk_hash,
352 ComponentInstaller* installer,
353 scoped_refptr<base::SequencedTaskRunner> task_runner) {
354 const base::FilePath crx_path = backup_path.Append(serialize::kCrxFileName);
355 if (!base::PathExists(crx_path) || base::DirectoryExists(crx_path)) {
356 return scoped_refptr<ComponentUnpacker>();
357 }
358
359 std::string fingerprint;
360 bool in_process = false;
361
362 const base::FilePath install_data_file_path =
363 backup_path.Append(serialize::kInstallDataFileName);
364 if (!base::PathExists(install_data_file_path)) {
365 return scoped_refptr<ComponentUnpacker>();
366 }
367
368 JSONFileValueSerializer serialize(install_data_file_path);
369 scoped_ptr<base::Value> root(serialize.Deserialize(NULL, NULL));
370 if (!root.get() || !root->IsType(base::Value::TYPE_DICTIONARY)) {
371 return scoped_refptr<ComponentUnpacker>();
372 }
373
374 scoped_ptr<base::DictionaryValue> metadata(
375 static_cast<base::DictionaryValue*>(root.release()));
376
377 base::ListValue* pk_hash_list = NULL;
378 if (!metadata->GetStringASCII(serialize::kKeyFingerprint, &fingerprint) ||
379 !metadata->GetBoolean(serialize::kKeyInProcess, &in_process) ||
380 !metadata->GetList(serialize::kKeyPKHash, &pk_hash_list) ||
381 pk_hash_list == NULL ||
382 pk_hash_list->GetSize() != pk_hash.size()) {
383 return scoped_refptr<ComponentUnpacker>();
384 }
385
386 for (size_t i = 0; i < pk_hash.size(); ++i) {
387 int value = 0;
388 if (!pk_hash_list->GetInteger(i, &value) ||
389 pk_hash[i] != static_cast<uint8>(value)) {
390 return scoped_refptr<ComponentUnpacker>();
391 }
392 }
393
394 return make_scoped_refptr(new ComponentUnpacker(
395 pk_hash, crx_path, fingerprint, installer, in_process, task_runner));
396 }
397
283 } // namespace component_updater 398 } // namespace component_updater
OLDNEW
« no previous file with comments | « chrome/browser/component_updater/component_unpacker.h ('k') | chrome/browser/component_updater/component_updater_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698