1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef COMPONENTS_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_
6#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_
7
8#include <string>
9
10#include "base/callback.h"
11#include "base/compiler_specific.h"
12#include "base/files/file_path.h"
13#include "base/macros.h"
14#include "base/memory/ref_counted.h"
15#include "components/component_updater/component_unpacker.h"
16
17namespace base {
18class DictionaryValue;
19}  // namespace base
20
21namespace component_updater {
22
23extern const char kOp[];
24extern const char kBsdiff[];
25extern const char kCourgette[];
26extern const char kInput[];
27extern const char kPatch[];
28
29class ComponentInstaller;
30
31class DeltaUpdateOp : public base::RefCountedThreadSafe<DeltaUpdateOp> {
32 public:
33  DeltaUpdateOp();
34
35  // Parses, runs, and verifies the operation. Calls |callback| with the
36  // result of the operation. The callback is called using |task_runner|.
37  void Run(const base::DictionaryValue* command_args,
38           const base::FilePath& input_dir,
39           const base::FilePath& unpack_dir,
40           ComponentInstaller* installer,
41           const ComponentUnpacker::Callback& callback,
42           scoped_refptr<base::SequencedTaskRunner> task_runner);
43
44 protected:
45  virtual ~DeltaUpdateOp();
46
47  scoped_refptr<base::SequencedTaskRunner> GetTaskRunner();
48
49  std::string output_sha256_;
50  base::FilePath output_abs_path_;
51
52 private:
53  friend class base::RefCountedThreadSafe<DeltaUpdateOp>;
54
55  ComponentUnpacker::Error CheckHash();
56
57  // Subclasses must override DoParseArguments to parse operation-specific
58  // arguments. DoParseArguments returns DELTA_OK on success; any other code
59  // represents failure.
60  virtual ComponentUnpacker::Error DoParseArguments(
61      const base::DictionaryValue* command_args,
62      const base::FilePath& input_dir,
63      ComponentInstaller* installer) = 0;
64
65  // Subclasses must override DoRun to actually perform the patching operation.
66  // They must call the provided callback when they have completed their
67  // operations. In practice, the provided callback is always for "DoneRunning".
68  virtual void DoRun(const ComponentUnpacker::Callback& callback) = 0;
69
70  // Callback given to subclasses for when they complete their operation.
71  // Validates the output, and posts a task to the patching operation's
72  // callback.
73  void DoneRunning(ComponentUnpacker::Error error, int extended_error);
74
75  ComponentUnpacker::Callback callback_;
76  scoped_refptr<base::SequencedTaskRunner> task_runner_;
77
78  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOp);
79};
80
81// A 'copy' operation takes a file currently residing on the disk and moves it
82// into the unpacking directory: this represents "no change" in the file being
83// installed.
84class DeltaUpdateOpCopy : public DeltaUpdateOp {
85 public:
86  DeltaUpdateOpCopy();
87
88 private:
89  virtual ~DeltaUpdateOpCopy();
90
91  // Overrides of DeltaUpdateOp.
92  virtual ComponentUnpacker::Error DoParseArguments(
93      const base::DictionaryValue* command_args,
94      const base::FilePath& input_dir,
95      ComponentInstaller* installer) OVERRIDE;
96
97  virtual void DoRun(const ComponentUnpacker::Callback& callback) OVERRIDE;
98
99  base::FilePath input_abs_path_;
100
101  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpCopy);
102};
103
104// A 'create' operation takes a full file that was sent in the delta update
105// archive and moves it into the unpacking directory: this represents the
106// addition of a new file, or a file so different that no bandwidth could be
107// saved by transmitting a differential update.
108class DeltaUpdateOpCreate : public DeltaUpdateOp {
109 public:
110  DeltaUpdateOpCreate();
111
112 private:
113  virtual ~DeltaUpdateOpCreate();
114
115  // Overrides of DeltaUpdateOp.
116  virtual ComponentUnpacker::Error DoParseArguments(
117      const base::DictionaryValue* command_args,
118      const base::FilePath& input_dir,
119      ComponentInstaller* installer) OVERRIDE;
120
121  virtual void DoRun(const ComponentUnpacker::Callback& callback) OVERRIDE;
122
123  base::FilePath patch_abs_path_;
124
125  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpCreate);
126};
127
128// An interface an embedder may fulfill to enable out-of-process patching.
129class OutOfProcessPatcher
130    : public base::RefCountedThreadSafe<OutOfProcessPatcher> {
131 public:
132  virtual void Patch(const std::string& operation,
133                     scoped_refptr<base::SequencedTaskRunner> task_runner,
134                     const base::FilePath& input_abs_path,
135                     const base::FilePath& patch_abs_path,
136                     const base::FilePath& output_abs_path,
137                     base::Callback<void(int result)> callback) = 0;
138
139 protected:
140  friend class base::RefCountedThreadSafe<OutOfProcessPatcher>;
141
142  virtual ~OutOfProcessPatcher() {}
143};
144
145// Both 'bsdiff' and 'courgette' operations take an existing file on disk,
146// and a bsdiff- or Courgette-format patch file provided in the delta update
147// package, and run bsdiff or Courgette to construct an output file in the
148// unpacking directory.
149class DeltaUpdateOpPatch : public DeltaUpdateOp {
150 public:
151  // |out_of_process_patcher| may be NULL.
152  DeltaUpdateOpPatch(const std::string& operation,
153                     scoped_refptr<OutOfProcessPatcher> out_of_process_patcher);
154
155 private:
156  virtual ~DeltaUpdateOpPatch();
157
158  // Overrides of DeltaUpdateOp.
159  virtual ComponentUnpacker::Error DoParseArguments(
160      const base::DictionaryValue* command_args,
161      const base::FilePath& input_dir,
162      ComponentInstaller* installer) OVERRIDE;
163
164  virtual void DoRun(const ComponentUnpacker::Callback& callback) OVERRIDE;
165
166  // |success_code| is the code that indicates a successful patch.
167  // |result| is the code the patching operation returned.
168  void DonePatching(const ComponentUnpacker::Callback& callback, int result);
169
170  std::string operation_;
171  scoped_refptr<OutOfProcessPatcher> out_of_process_patcher_;
172  base::FilePath patch_abs_path_;
173  base::FilePath input_abs_path_;
174
175  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpPatch);
176};
177
178DeltaUpdateOp* CreateDeltaUpdateOp(
179    const std::string& operation,
180    scoped_refptr<OutOfProcessPatcher> out_of_process_patcher);
181
182}  // namespace component_updater
183
184#endif  // COMPONENTS_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_
185