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