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)#ifndef COMPONENTS_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_
603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <stdint.h>
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/callback.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/json/json_file_value_serializer.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/macros.h"
16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/memory/ref_counted.h"
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/sequenced_task_runner.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace component_updater {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ComponentInstaller;
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass ComponentPatcher;
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class OutOfProcessPatcher;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Deserializes the CRX manifest. The top level must be a dictionary.
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)scoped_ptr<base::DictionaryValue> ReadManifest(
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const base::FilePath& unpack_path);
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In charge of unpacking the component CRX package and verifying that it is
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// well formed and the cryptographic signature is correct. If there is no
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// error the component specific installer will be invoked to proceed with
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the component installation or update.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This class should be used only by the component updater. It is inspired by
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and overlaps with code in the extension's SandboxedUnpacker.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The main differences are:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The public key hash is full SHA256.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Does not use a sandboxed unpacker. A valid component is fully trusted.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The manifest can have different attributes and resources are not
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   transcoded.
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// If the CRX is a delta CRX, the flow is:
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//   [ComponentUpdater]      [ComponentPatcher]
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//   Unpack
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ Verify
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ Unzip
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ BeginPatching ---> DifferentialUpdatePatch
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                             ...
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//   EndPatching <------------ ...
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ Install
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ Finish
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// For a full CRX, the flow is:
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//   [ComponentUpdater]
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//   Unpack
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ Verify
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ Unzip
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ BeginPatching
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//          |
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//          V
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//   EndPatching
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ Install
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     \_ Finish
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// In both cases, if there is an error at any point, the remaining steps will
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// be skipped and Finish will be called.
68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass ComponentUnpacker : public base::RefCountedThreadSafe<ComponentUnpacker> {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Possible error conditions.
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add only to the bottom of this enum; the order must be kept stable.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Error {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kNone,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kInvalidParams,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kInvalidFile,
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kUnzipPathError,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kUnzipFailed,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kNoManifest,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kBadManifest,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kBadExtension,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kInvalidId,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kInstallerError,
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kIoError,
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kDeltaVerificationFailure,
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kDeltaBadCommands,
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kDeltaUnsupportedCommand,
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kDeltaOperationFailure,
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kDeltaPatchProcessFailure,
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kDeltaMissingExistingFile,
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kFingerprintWriteFailed,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  typedef base::Callback<void(Error, int)> Callback;
94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Constructs an unpacker for a specific component unpacking operation.
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |pk_hash| is the expected/ public key SHA256 hash. |path| is the current
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // location of the CRX.
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ComponentUnpacker(const std::vector<uint8_t>& pk_hash,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const base::FilePath& path,
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    const std::string& fingerprint,
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    ComponentInstaller* installer,
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    scoped_refptr<OutOfProcessPatcher> out_of_process_patcher,
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    scoped_refptr<base::SequencedTaskRunner> task_runner);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Begins the actual unpacking of the files. May invoke a patcher if the
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // package is a differential update. Calls |callback| with the result.
107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void Unpack(const Callback& callback);
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  friend class base::RefCountedThreadSafe<ComponentUnpacker>;
111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual ~ComponentUnpacker();
113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool UnpackInternal();
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The first step of unpacking is to verify the file. Returns false if an
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // error is encountered, the file is malformed, or the file is incorrectly
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // signed.
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool Verify();
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The second step of unpacking is to unzip. Returns false if an error
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // occurs as part of unzipping.
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool Unzip();
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The third step is to optionally patch files - this is a no-op for full
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // (non-differential) updates. This step is asynchronous. Returns false if an
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // error is encountered.
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool BeginPatching();
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // When patching is complete, EndPatching is called before moving on to step
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // four.
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void EndPatching(Error error, int extended_error);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The fourth step is to install the unpacked component.
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Install();
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The final step is to do clean-up for things that can't be tidied as we go.
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If there is an error at any step, the remaining steps are skipped and
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // and Finish is called.
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Finish is responsible for calling the callback provided in Start().
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Finish();
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<uint8_t> pk_hash_;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath path_;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath unpack_path_;
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath unpack_diff_path_;
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool is_delta_;
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string fingerprint_;
149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  scoped_refptr<ComponentPatcher> patcher_;
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ComponentInstaller* installer_;
151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Callback callback_;
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<OutOfProcessPatcher> out_of_process_patcher_;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Error error_;
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int extended_error_;
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> task_runner_;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ComponentUnpacker);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace component_updater
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif  // COMPONENTS_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_
163