1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_
#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_
#include <stdint.h>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/json/json_file_value_serializer.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/sequenced_task_runner.h"
namespace component_updater {
class ComponentInstaller;
class ComponentPatcher;
class OutOfProcessPatcher;
// Deserializes the CRX manifest. The top level must be a dictionary.
scoped_ptr<base::DictionaryValue> ReadManifest(
const base::FilePath& unpack_path);
// In charge of unpacking the component CRX package and verifying that it is
// well formed and the cryptographic signature is correct. If there is no
// error the component specific installer will be invoked to proceed with
// the component installation or update.
//
// This class should be used only by the component updater. It is inspired by
// and overlaps with code in the extension's SandboxedUnpacker.
// The main differences are:
// - The public key hash is full SHA256.
// - Does not use a sandboxed unpacker. A valid component is fully trusted.
// - The manifest can have different attributes and resources are not
// transcoded.
//
// If the CRX is a delta CRX, the flow is:
// [ComponentUpdater] [ComponentPatcher]
// Unpack
// \_ Verify
// \_ Unzip
// \_ BeginPatching ---> DifferentialUpdatePatch
// ...
// EndPatching <------------ ...
// \_ Install
// \_ Finish
//
// For a full CRX, the flow is:
// [ComponentUpdater]
// Unpack
// \_ Verify
// \_ Unzip
// \_ BeginPatching
// |
// V
// EndPatching
// \_ Install
// \_ Finish
//
// In both cases, if there is an error at any point, the remaining steps will
// be skipped and Finish will be called.
class ComponentUnpacker : public base::RefCountedThreadSafe<ComponentUnpacker> {
public:
// Possible error conditions.
// Add only to the bottom of this enum; the order must be kept stable.
enum Error {
kNone,
kInvalidParams,
kInvalidFile,
kUnzipPathError,
kUnzipFailed,
kNoManifest,
kBadManifest,
kBadExtension,
kInvalidId,
kInstallerError,
kIoError,
kDeltaVerificationFailure,
kDeltaBadCommands,
kDeltaUnsupportedCommand,
kDeltaOperationFailure,
kDeltaPatchProcessFailure,
kDeltaMissingExistingFile,
kFingerprintWriteFailed,
};
typedef base::Callback<void(Error, int)> Callback;
// Constructs an unpacker for a specific component unpacking operation.
// |pk_hash| is the expected/ public key SHA256 hash. |path| is the current
// location of the CRX.
ComponentUnpacker(const std::vector<uint8_t>& pk_hash,
const base::FilePath& path,
const std::string& fingerprint,
ComponentInstaller* installer,
scoped_refptr<OutOfProcessPatcher> out_of_process_patcher,
scoped_refptr<base::SequencedTaskRunner> task_runner);
// Begins the actual unpacking of the files. May invoke a patcher if the
// package is a differential update. Calls |callback| with the result.
void Unpack(const Callback& callback);
private:
friend class base::RefCountedThreadSafe<ComponentUnpacker>;
virtual ~ComponentUnpacker();
bool UnpackInternal();
// The first step of unpacking is to verify the file. Returns false if an
// error is encountered, the file is malformed, or the file is incorrectly
// signed.
bool Verify();
// The second step of unpacking is to unzip. Returns false if an error
// occurs as part of unzipping.
bool Unzip();
// The third step is to optionally patch files - this is a no-op for full
// (non-differential) updates. This step is asynchronous. Returns false if an
// error is encountered.
bool BeginPatching();
// When patching is complete, EndPatching is called before moving on to step
// four.
void EndPatching(Error error, int extended_error);
// The fourth step is to install the unpacked component.
void Install();
// The final step is to do clean-up for things that can't be tidied as we go.
// If there is an error at any step, the remaining steps are skipped and
// and Finish is called.
// Finish is responsible for calling the callback provided in Start().
void Finish();
std::vector<uint8_t> pk_hash_;
base::FilePath path_;
base::FilePath unpack_path_;
base::FilePath unpack_diff_path_;
bool is_delta_;
std::string fingerprint_;
scoped_refptr<ComponentPatcher> patcher_;
ComponentInstaller* installer_;
Callback callback_;
scoped_refptr<OutOfProcessPatcher> out_of_process_patcher_;
Error error_;
int extended_error_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(ComponentUnpacker);
};
} // namespace component_updater
#endif // COMPONENTS_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_
|