103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_unpacker.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <stdint.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/file_path.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/files/scoped_file.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_file_value_serializer.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h" 171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/logging.h" 1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/numerics/safe_conversions.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/values.h" 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_patcher.h" 2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_patcher_operation.h" 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_updater_service.h" 256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/crx_file/constants.h" 266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/crx_file/crx_file.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/secure_hash.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/signature_verifier.h" 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/zlib/google/zip.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using crypto::SecureHash; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace component_updater { 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class makes sure that the CRX digital signature is valid 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and well formed. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CRXValidator { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit CRXValidator(FILE* crx_file) : valid_(false), is_delta_(false) { 426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) crx_file::CrxFile::Header header; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len = fread(&header, 1, sizeof(header), crx_file); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < sizeof(header)) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) crx_file::CrxFile::Error error; 486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<crx_file::CrxFile> crx( 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) crx_file::CrxFile::Parse(header, &error)); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!crx.get()) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) is_delta_ = crx_file::CrxFile::HeaderIsDelta(header); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint8_t> key(header.key_size); 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci len = fread(&key[0], sizeof(uint8_t), header.key_size, crx_file); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < header.key_size) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint8_t> signature(header.signature_size); 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci len = 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci fread(&signature[0], sizeof(uint8_t), header.signature_size, crx_file); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < header.signature_size) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::SignatureVerifier verifier; 666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!verifier.VerifyInit(crx_file::kSignatureAlgorithm, 6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::checked_cast<int>( 6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) sizeof(crx_file::kSignatureAlgorithm)), 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) &signature[0], 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::checked_cast<int>(signature.size()), 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) &key[0], 7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::checked_cast<int>(key.size()))) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signature verification initialization failed. This is most likely 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caused by a public key in the wrong format (should encode algorithm). 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t kBufSize = 8 * 1024; 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<uint8_t[]> buf(new uint8_t[kBufSize]); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((len = fread(buf.get(), 1, kBufSize, crx_file)) > 0) 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) verifier.VerifyUpdate(buf.get(), base::checked_cast<int>(len)); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!verifier.VerifyFinal()) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public_key_.swap(key); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_ = true; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool valid() const { return valid_; } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_delta() const { return is_delta_; } 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<uint8_t>& public_key() const { return public_key_; } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool valid_; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_delta_; 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint8_t> public_key_; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ComponentUnpacker::ComponentUnpacker( 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<uint8_t>& pk_hash, 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& path, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& fingerprint, 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ComponentInstaller* installer, 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<OutOfProcessPatcher> out_of_process_patcher, 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> task_runner) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : pk_hash_(pk_hash), 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) path_(path), 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_delta_(false), 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fingerprint_(fingerprint), 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) installer_(installer), 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) out_of_process_patcher_(out_of_process_patcher), 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) error_(kNone), 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extended_error_(0), 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_runner_(task_runner) { 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(cpu): add a specific attribute check to a component json that the 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extension unpacker will reject, so that a component cannot be installed 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as an extension. 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)scoped_ptr<base::DictionaryValue> ReadManifest( 1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const base::FilePath& unpack_path) { 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath manifest = 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(manifest)) 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return scoped_ptr<base::DictionaryValue>(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONFileValueSerializer serializer(manifest); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!root.get()) 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return scoped_ptr<base::DictionaryValue>(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!root->IsType(base::Value::TYPE_DICTIONARY)) 1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return scoped_ptr<base::DictionaryValue>(); 1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return scoped_ptr<base::DictionaryValue>( 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static_cast<base::DictionaryValue*>(root.release())).Pass(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ComponentUnpacker::UnpackInternal() { 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return Verify() && Unzip() && BeginPatching(); 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ComponentUnpacker::Unpack(const Callback& callback) { 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_ = callback; 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!UnpackInternal()) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Finish(); 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ComponentUnpacker::Verify() { 1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VLOG(1) << "Verifying component: " << path_.value(); 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pk_hash_.empty() || path_.empty()) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = kInvalidParams; 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, validate the CRX header and signature. As of today 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this is SHA1 with RSA 1024. 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::ScopedFILE file(base::OpenFile(path_, "rb")); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file.get()) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = kInvalidFile; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRXValidator validator(file.get()); 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) file.reset(); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!validator.valid()) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = kInvalidFile; 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_delta_ = validator.is_delta(); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // File is valid and the digital signature matches. Now make sure 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the public key hash matches the expected hash. If they do we fully 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // trust this CRX. 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint8_t hash[32] = {}; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256)); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sha256->Update(&(validator.public_key()[0]), validator.public_key().size()); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sha256->Finish(hash, arraysize(hash)); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!std::equal(pk_hash_.begin(), pk_hash_.end(), hash)) { 1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VLOG(1) << "Hash mismatch: " << path_.value(); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = kInvalidId; 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VLOG(1) << "Verification successful: " << path_.value(); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ComponentUnpacker::Unzip() { 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_; 1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VLOG(1) << "Unpacking in: " << destination.value(); 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateNewTempDirectory(base::FilePath::StringType(), 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &destination)) { 1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VLOG(1) << "Unable to create temporary directory for unpacking."; 196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch error_ = kUnzipPathError; 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!zip::Unzip(path_, destination)) { 2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VLOG(1) << "Unzipping failed."; 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) error_ = kUnzipFailed; 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VLOG(1) << "Unpacked successfully"; 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ComponentUnpacker::BeginPatching() { 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (is_delta_) { // Package is a diff package. 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Use a different temp directory for the patch output files. 211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateNewTempDirectory(base::FilePath::StringType(), 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &unpack_path_)) { 213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch error_ = kUnzipPathError; 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch patcher_ = new ComponentPatcher(unpack_diff_path_, 217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch unpack_path_, 218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch installer_, 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) out_of_process_patcher_, 220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch task_runner_); 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_runner_->PostTask( 222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&ComponentPatcher::Start, 224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch patcher_, 225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&ComponentUnpacker::EndPatching, 226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_refptr<ComponentUnpacker>(this)))); 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 228effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch task_runner_->PostTask(FROM_HERE, 229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&ComponentUnpacker::EndPatching, 230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_refptr<ComponentUnpacker>(this), 231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kNone, 232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 0)); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ComponentUnpacker::EndPatching(Error error, int extended_error) { 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) error_ = error; 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extended_error_ = extended_error; 240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch patcher_ = NULL; 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (error_ != kNone) { 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Finish(); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Optimization: clean up patch files early, in case disk space is too low to 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // install otherwise. 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!unpack_diff_path_.empty()) { 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DeleteFile(unpack_diff_path_, true); 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unpack_diff_path_.clear(); 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Install(); 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Finish(); 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ComponentUnpacker::Install() { 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Write the fingerprint to disk. 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (static_cast<int>(fingerprint_.size()) != 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WriteFile( 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unpack_path_.Append(FILE_PATH_LITERAL("manifest.fingerprint")), 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fingerprint_.c_str(), 26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::checked_cast<int>(fingerprint_.size()))) { 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch error_ = kFingerprintWriteFailed; 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> manifest(ReadManifest(unpack_path_)); 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!manifest.get()) { 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) error_ = kBadManifest; 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(error_ == kNone); 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!installer_->Install(*manifest, unpack_path_)) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = kInstallerError; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ComponentUnpacker::Finish() { 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!unpack_diff_path_.empty()) 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DeleteFile(unpack_diff_path_, true); 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!unpack_path_.empty()) 2817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(unpack_path_, true); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_.Run(error_, extended_error_); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ComponentUnpacker::~ComponentUnpacker() { 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace component_updater 289