Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Side by Side Diff: chrome/browser/component_updater/component_patcher_operation.cc

Issue 25909005: Use UtilityProcessHost to patch files. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@nonblocking
Patch Set: Fix ASAN failure, rebase to LKGR/259825 Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/component_updater/component_patcher_operation.h" 5 #include "chrome/browser/component_updater/component_patcher_operation.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h"
10 #include "base/file_util.h" 11 #include "base/file_util.h"
11 #include "base/files/memory_mapped_file.h" 12 #include "base/files/memory_mapped_file.h"
12 #include "base/json/json_file_value_serializer.h" 13 #include "base/json/json_file_value_serializer.h"
13 #include "base/memory/scoped_handle.h" 14 #include "base/memory/scoped_handle.h"
14 #include "base/path_service.h" 15 #include "base/path_service.h"
15 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
16 #include "chrome/browser/component_updater/component_patcher.h" 17 #include "chrome/browser/component_updater/component_patcher.h"
17 #include "chrome/browser/component_updater/component_updater_service.h" 18 #include "chrome/browser/component_updater/component_updater_service.h"
19 #include "chrome/common/chrome_utility_messages.h"
18 #include "chrome/common/extensions/extension_constants.h" 20 #include "chrome/common/extensions/extension_constants.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/utility_process_host.h"
23 #include "courgette/courgette.h"
24 #include "courgette/third_party/bsdiff.h"
19 #include "crypto/secure_hash.h" 25 #include "crypto/secure_hash.h"
20 #include "crypto/sha2.h" 26 #include "crypto/sha2.h"
21 #include "crypto/signature_verifier.h" 27 #include "crypto/signature_verifier.h"
22 #include "extensions/common/crx_file.h" 28 #include "extensions/common/crx_file.h"
29 #include "ipc/ipc_message_macros.h"
23 #include "third_party/zlib/google/zip.h" 30 #include "third_party/zlib/google/zip.h"
24 31
25 using crypto::SecureHash; 32 using crypto::SecureHash;
26 33
27 namespace component_updater { 34 namespace component_updater {
28 35
29 namespace { 36 namespace {
30 37
31 const char kInput[] = "input"; 38 const char kInput[] = "input";
32 const char kOp[] = "op"; 39 const char kOp[] = "op";
33 const char kOutput[] = "output"; 40 const char kOutput[] = "output";
34 const char kPatch[] = "patch"; 41 const char kPatch[] = "patch";
35 const char kSha256[] = "sha256"; 42 const char kSha256[] = "sha256";
36 43
44 // The integer offset disambiguates between overlapping error ranges.
45 const int kCourgetteErrorOffset = 300;
46 const int kBsdiffErrorOffset = 600;
47
48 class CourgetteTraits : public DeltaUpdateOpPatchStrategy {
49 public:
50 virtual int GetErrorOffset() const OVERRIDE;
51 virtual int GetSuccessCode() const OVERRIDE;
52 virtual scoped_ptr<IPC::Message> GetPatchMessage(
53 base::FilePath input_abs_path,
54 base::FilePath patch_abs_path,
55 base::FilePath output_abs_path) OVERRIDE;
56 virtual int Patch(base::FilePath input_abs_path,
57 base::FilePath patch_abs_path,
58 base::FilePath output_abs_path) OVERRIDE;
59 };
60
61 int CourgetteTraits::GetErrorOffset() const {
62 return kCourgetteErrorOffset;
63 }
64
65 int CourgetteTraits::GetSuccessCode() const {
66 return courgette::C_OK;
67 }
68
69 scoped_ptr<IPC::Message> CourgetteTraits::GetPatchMessage(
70 base::FilePath input_abs_path,
71 base::FilePath patch_abs_path,
72 base::FilePath output_abs_path) {
73 return scoped_ptr<IPC::Message>(
74 new ChromeUtilityMsg_PatchFileCourgette(input_abs_path,
75 patch_abs_path,
76 output_abs_path));
77 }
78
79 int CourgetteTraits::Patch(base::FilePath input_abs_path,
80 base::FilePath patch_abs_path,
81 base::FilePath output_abs_path) {
82 return courgette::ApplyEnsemblePatch(input_abs_path.value().c_str(),
83 patch_abs_path.value().c_str(),
84 output_abs_path.value().c_str());
85 }
86
87 class BsdiffTraits : public DeltaUpdateOpPatchStrategy {
88 public:
89 virtual int GetErrorOffset() const OVERRIDE;
90 virtual int GetSuccessCode() const OVERRIDE;
91 virtual scoped_ptr<IPC::Message> GetPatchMessage(
92 base::FilePath input_abs_path,
93 base::FilePath patch_abs_path,
94 base::FilePath output_abs_path) OVERRIDE;
95 virtual int Patch(base::FilePath input_abs_path,
96 base::FilePath patch_abs_path,
97 base::FilePath output_abs_path) OVERRIDE;
98 };
99
100 int BsdiffTraits::GetErrorOffset() const {
101 return kBsdiffErrorOffset;
102 }
103
104 int BsdiffTraits::GetSuccessCode() const {
105 return courgette::OK;
106 }
107
108 scoped_ptr<IPC::Message> BsdiffTraits::GetPatchMessage(
109 base::FilePath input_abs_path,
110 base::FilePath patch_abs_path,
111 base::FilePath output_abs_path) {
112 return scoped_ptr<IPC::Message>(
113 new ChromeUtilityMsg_PatchFileBsdiff(input_abs_path,
114 patch_abs_path,
115 output_abs_path));
116 }
117
118 int BsdiffTraits::Patch(base::FilePath input_abs_path,
119 base::FilePath patch_abs_path,
120 base::FilePath output_abs_path) {
121 return courgette::ApplyBinaryPatch(input_abs_path,
122 patch_abs_path,
123 output_abs_path);
124 }
125
37 } // namespace 126 } // namespace
38 127
39 DeltaUpdateOp* CreateDeltaUpdateOp(base::DictionaryValue* command) { 128 DeltaUpdateOpPatchStrategy::~DeltaUpdateOpPatchStrategy() {
40 std::string operation; 129 }
41 if (!command->GetString(kOp, &operation)) 130
42 return NULL; 131 DeltaUpdateOp* CreateDeltaUpdateOp(const std::string& operation) {
43 if (operation == "copy") 132 if (operation == "copy") {
44 return new DeltaUpdateOpCopy(); 133 return new DeltaUpdateOpCopy();
45 else if (operation == "create") 134 } else if (operation == "create") {
46 return new DeltaUpdateOpCreate(); 135 return new DeltaUpdateOpCreate();
47 else if (operation == "bsdiff") 136 } else if (operation == "bsdiff") {
48 return new DeltaUpdateOpPatchBsdiff(); 137 scoped_ptr<DeltaUpdateOpPatchStrategy> strategy(new BsdiffTraits());
49 else if (operation == "courgette") 138 return new DeltaUpdateOpPatch(strategy.Pass());
50 return new DeltaUpdateOpPatchCourgette(); 139 } else if (operation == "courgette") {
140 scoped_ptr<DeltaUpdateOpPatchStrategy> strategy(new CourgetteTraits());
141 return new DeltaUpdateOpPatch(strategy.Pass());
142 }
51 return NULL; 143 return NULL;
52 } 144 }
53 145
54 DeltaUpdateOp::DeltaUpdateOp() {} 146 DeltaUpdateOp* CreateDeltaUpdateOp(const base::DictionaryValue& command) {
147 std::string operation;
148 if (!command.GetString(kOp, &operation))
149 return NULL;
150 return CreateDeltaUpdateOp(operation);
151 }
152
153 DeltaUpdateOp::DeltaUpdateOp() : in_process_(false) {}
55 154
56 DeltaUpdateOp::~DeltaUpdateOp() {} 155 DeltaUpdateOp::~DeltaUpdateOp() {}
57 156
58 ComponentUnpacker::Error DeltaUpdateOp::Run(base::DictionaryValue* command_args, 157 void DeltaUpdateOp::Run(
59 const base::FilePath& input_dir, 158 const base::DictionaryValue* command_args,
60 const base::FilePath& unpack_dir, 159 const base::FilePath& input_dir,
61 ComponentPatcher* patcher, 160 const base::FilePath& unpack_dir,
62 ComponentInstaller* installer, 161 ComponentInstaller* installer,
63 int* error) { 162 bool in_process,
163 const ComponentUnpacker::Callback& callback,
164 scoped_refptr<base::SequencedTaskRunner> task_runner) {
165 callback_ = callback;
166 in_process_ = in_process;
167 task_runner_ = task_runner;
64 std::string output_rel_path; 168 std::string output_rel_path;
65 if (!command_args->GetString(kOutput, &output_rel_path) || 169 if (!command_args->GetString(kOutput, &output_rel_path) ||
66 !command_args->GetString(kSha256, &output_sha256_)) 170 !command_args->GetString(kSha256, &output_sha256_)) {
67 return ComponentUnpacker::kDeltaBadCommands; 171 DoneRunning(ComponentUnpacker::kDeltaBadCommands, 0);
172 return;
173 }
68 174
69 output_abs_path_ = unpack_dir.Append( 175 output_abs_path_ = unpack_dir.Append(
70 base::FilePath::FromUTF8Unsafe(output_rel_path)); 176 base::FilePath::FromUTF8Unsafe(output_rel_path));
71 ComponentUnpacker::Error parse_result = DoParseArguments( 177 ComponentUnpacker::Error parse_result = DoParseArguments(
72 command_args, input_dir, installer); 178 command_args, input_dir, installer);
73 if (parse_result != ComponentUnpacker::kNone) 179 if (parse_result != ComponentUnpacker::kNone) {
74 return parse_result; 180 DoneRunning(parse_result, 0);
181 return;
182 }
75 183
76 const base::FilePath parent = output_abs_path_.DirName(); 184 const base::FilePath parent = output_abs_path_.DirName();
77 if (!base::DirectoryExists(parent)) { 185 if (!base::DirectoryExists(parent)) {
78 if (!base::CreateDirectory(parent)) 186 if (!base::CreateDirectory(parent)) {
79 return ComponentUnpacker::kIoError; 187 DoneRunning(ComponentUnpacker::kIoError, 0);
188 return;
189 }
80 } 190 }
81 191
82 ComponentUnpacker::Error run_result = DoRun(patcher, error); 192 DoRun(base::Bind(&DeltaUpdateOp::DoneRunning,
83 if (run_result != ComponentUnpacker::kNone) 193 scoped_refptr<DeltaUpdateOp>(this)));
84 return run_result; 194 }
85 195
86 return CheckHash(); 196 void DeltaUpdateOp::DoneRunning(ComponentUnpacker::Error error,
197 int extended_error) {
198 if (error == ComponentUnpacker::kNone)
199 error = CheckHash();
200 task_runner_->PostTask(FROM_HERE,
201 base::Bind(callback_, error, extended_error));
202 callback_.Reset();
87 } 203 }
88 204
89 // Uses the hash as a checksum to confirm that the file now residing in the 205 // Uses the hash as a checksum to confirm that the file now residing in the
90 // output directory probably has the contents it should. 206 // output directory probably has the contents it should.
91 ComponentUnpacker::Error DeltaUpdateOp::CheckHash() { 207 ComponentUnpacker::Error DeltaUpdateOp::CheckHash() {
92 std::vector<uint8> expected_hash; 208 std::vector<uint8> expected_hash;
93 if (!base::HexStringToBytes(output_sha256_, &expected_hash) || 209 if (!base::HexStringToBytes(output_sha256_, &expected_hash) ||
94 expected_hash.size() != crypto::kSHA256Length) 210 expected_hash.size() != crypto::kSHA256Length)
95 return ComponentUnpacker::kDeltaVerificationFailure; 211 return ComponentUnpacker::kDeltaVerificationFailure;
96 212
97 base::MemoryMappedFile output_file_mmapped; 213 base::MemoryMappedFile output_file_mmapped;
98 if (!output_file_mmapped.Initialize(output_abs_path_)) 214 if (!output_file_mmapped.Initialize(output_abs_path_))
99 return ComponentUnpacker::kDeltaVerificationFailure; 215 return ComponentUnpacker::kDeltaVerificationFailure;
100 216
101 uint8 actual_hash[crypto::kSHA256Length] = {0}; 217 uint8 actual_hash[crypto::kSHA256Length] = {0};
102 const scoped_ptr<SecureHash> hasher(SecureHash::Create(SecureHash::SHA256)); 218 const scoped_ptr<SecureHash> hasher(SecureHash::Create(SecureHash::SHA256));
103 hasher->Update(output_file_mmapped.data(), output_file_mmapped.length()); 219 hasher->Update(output_file_mmapped.data(), output_file_mmapped.length());
104 hasher->Finish(actual_hash, sizeof(actual_hash)); 220 hasher->Finish(actual_hash, sizeof(actual_hash));
105 if (memcmp(actual_hash, &expected_hash[0], sizeof(actual_hash))) 221 if (memcmp(actual_hash, &expected_hash[0], sizeof(actual_hash)))
106 return ComponentUnpacker::kDeltaVerificationFailure; 222 return ComponentUnpacker::kDeltaVerificationFailure;
107 223
108 return ComponentUnpacker::kNone; 224 return ComponentUnpacker::kNone;
109 } 225 }
110 226
227 bool DeltaUpdateOp::InProcess() {
228 return in_process_;
229 }
230
111 DeltaUpdateOpCopy::DeltaUpdateOpCopy() {} 231 DeltaUpdateOpCopy::DeltaUpdateOpCopy() {}
112 232
233 DeltaUpdateOpCopy::~DeltaUpdateOpCopy() {}
234
113 ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments( 235 ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments(
114 base::DictionaryValue* command_args, 236 const base::DictionaryValue* command_args,
115 const base::FilePath& input_dir, 237 const base::FilePath& input_dir,
116 ComponentInstaller* installer) { 238 ComponentInstaller* installer) {
117 std::string input_rel_path; 239 std::string input_rel_path;
118 if (!command_args->GetString(kInput, &input_rel_path)) 240 if (!command_args->GetString(kInput, &input_rel_path))
119 return ComponentUnpacker::kDeltaBadCommands; 241 return ComponentUnpacker::kDeltaBadCommands;
120 242
121 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_)) 243 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
122 return ComponentUnpacker::kDeltaMissingExistingFile; 244 return ComponentUnpacker::kDeltaMissingExistingFile;
123 245
124 return ComponentUnpacker::kNone; 246 return ComponentUnpacker::kNone;
125 } 247 }
126 248
127 ComponentUnpacker::Error DeltaUpdateOpCopy::DoRun(ComponentPatcher*, 249 void DeltaUpdateOpCopy::DoRun(const ComponentUnpacker::Callback& callback) {
128 int* error) {
129 *error = 0;
130 if (!base::CopyFile(input_abs_path_, output_abs_path_)) 250 if (!base::CopyFile(input_abs_path_, output_abs_path_))
131 return ComponentUnpacker::kDeltaOperationFailure; 251 callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0);
132 252 else
133 return ComponentUnpacker::kNone; 253 callback.Run(ComponentUnpacker::kNone, 0);
134 } 254 }
135 255
136 DeltaUpdateOpCreate::DeltaUpdateOpCreate() {} 256 DeltaUpdateOpCreate::DeltaUpdateOpCreate() {}
137 257
258 DeltaUpdateOpCreate::~DeltaUpdateOpCreate() {}
259
138 ComponentUnpacker::Error DeltaUpdateOpCreate::DoParseArguments( 260 ComponentUnpacker::Error DeltaUpdateOpCreate::DoParseArguments(
139 base::DictionaryValue* command_args, 261 const base::DictionaryValue* command_args,
140 const base::FilePath& input_dir, 262 const base::FilePath& input_dir,
141 ComponentInstaller* installer) { 263 ComponentInstaller* installer) {
142 std::string patch_rel_path; 264 std::string patch_rel_path;
143 if (!command_args->GetString(kPatch, &patch_rel_path)) 265 if (!command_args->GetString(kPatch, &patch_rel_path))
144 return ComponentUnpacker::kDeltaBadCommands; 266 return ComponentUnpacker::kDeltaBadCommands;
145 267
146 patch_abs_path_ = input_dir.Append( 268 patch_abs_path_ = input_dir.Append(
147 base::FilePath::FromUTF8Unsafe(patch_rel_path)); 269 base::FilePath::FromUTF8Unsafe(patch_rel_path));
148 270
149 return ComponentUnpacker::kNone; 271 return ComponentUnpacker::kNone;
150 } 272 }
151 273
152 ComponentUnpacker::Error DeltaUpdateOpCreate::DoRun(ComponentPatcher*, 274 void DeltaUpdateOpCreate::DoRun(const ComponentUnpacker::Callback& callback) {
153 int* error) {
154 *error = 0;
155 if (!base::Move(patch_abs_path_, output_abs_path_)) 275 if (!base::Move(patch_abs_path_, output_abs_path_))
156 return ComponentUnpacker::kDeltaOperationFailure; 276 callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0);
157 277 else
158 return ComponentUnpacker::kNone; 278 callback.Run(ComponentUnpacker::kNone, 0);
159 } 279 }
160 280
161 DeltaUpdateOpPatchBsdiff::DeltaUpdateOpPatchBsdiff() {} 281 DeltaUpdateOpPatchHost::DeltaUpdateOpPatchHost(
282 scoped_refptr<DeltaUpdateOpPatch> patcher) : patcher_(patcher) {
283 }
162 284
163 ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoParseArguments( 285 DeltaUpdateOpPatchHost::~DeltaUpdateOpPatchHost() {
164 base::DictionaryValue* command_args, 286 }
287
288 void DeltaUpdateOpPatchHost::StartProcess(scoped_ptr<IPC::Message> message) {
289 // The DeltaUpdateOpPatchHost is not responsible for deleting the
290 // UtilityProcessHost object.
291 content::UtilityProcessHost* host = content::UtilityProcessHost::Create(
292 this, base::MessageLoopProxy::current().get());
293 host->DisableSandbox();
294 host->Send(message.get());
295 }
296
297 bool DeltaUpdateOpPatchHost::OnMessageReceived(const IPC::Message& message) {
298 bool handled = true;
299 IPC_BEGIN_MESSAGE_MAP(DeltaUpdateOpPatchHost, message)
300 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PatchFile_Succeeded,
301 OnPatchSucceeded)
302 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PatchFile_Failed,
303 OnPatchFailed)
304 IPC_MESSAGE_UNHANDLED(handled = false)
305 IPC_END_MESSAGE_MAP()
306 return handled;
307 }
308
309 void DeltaUpdateOpPatchHost::OnPatchSucceeded() {
310 patcher_->DonePatching(ComponentUnpacker::kNone, 0);
311 patcher_ = NULL;
312 }
313
314 void DeltaUpdateOpPatchHost::OnPatchFailed(int error_code) {
315 patcher_->DonePatching(ComponentUnpacker::kDeltaOperationFailure, error_code);
316 patcher_ = NULL;
317 }
318
319 void DeltaUpdateOpPatchHost::OnProcessCrashed(int exit_code) {
320 patcher_->DonePatching(ComponentUnpacker::kDeltaPatchProcessFailure,
321 exit_code);
322 patcher_ = NULL;
323 }
324
325 DeltaUpdateOpPatch::DeltaUpdateOpPatch(
326 scoped_ptr<DeltaUpdateOpPatchStrategy> strategy) {
327 strategy_ = strategy.Pass();
328 }
329
330 DeltaUpdateOpPatch::~DeltaUpdateOpPatch() {
331 }
332
333 ComponentUnpacker::Error DeltaUpdateOpPatch::DoParseArguments(
334 const base::DictionaryValue* command_args,
165 const base::FilePath& input_dir, 335 const base::FilePath& input_dir,
166 ComponentInstaller* installer) { 336 ComponentInstaller* installer) {
167 std::string patch_rel_path; 337 std::string patch_rel_path;
168 std::string input_rel_path;
169 if (!command_args->GetString(kPatch, &patch_rel_path) ||
170 !command_args->GetString(kInput, &input_rel_path))
171 return ComponentUnpacker::kDeltaBadCommands;
172
173 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
174 return ComponentUnpacker::kDeltaMissingExistingFile;
175
176 patch_abs_path_ = input_dir.Append(
177 base::FilePath::FromUTF8Unsafe(patch_rel_path));
178
179 return ComponentUnpacker::kNone;
180 }
181
182 ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoRun(
183 ComponentPatcher* patcher,
184 int* error) {
185 *error = 0;
186 return patcher->Patch(ComponentPatcher::kPatchTypeBsdiff,
187 input_abs_path_,
188 patch_abs_path_,
189 output_abs_path_,
190 error);
191 }
192
193 DeltaUpdateOpPatchCourgette::DeltaUpdateOpPatchCourgette() {}
194
195 ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoParseArguments(
196 base::DictionaryValue* command_args,
197 const base::FilePath& input_dir,
198 ComponentInstaller* installer) {
199 std::string patch_rel_path;
200 std::string input_rel_path; 338 std::string input_rel_path;
201 if (!command_args->GetString(kPatch, &patch_rel_path) || 339 if (!command_args->GetString(kPatch, &patch_rel_path) ||
202 !command_args->GetString(kInput, &input_rel_path)) 340 !command_args->GetString(kInput, &input_rel_path))
203 return ComponentUnpacker::kDeltaBadCommands; 341 return ComponentUnpacker::kDeltaBadCommands;
204 342
205 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_)) 343 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
206 return ComponentUnpacker::kDeltaMissingExistingFile; 344 return ComponentUnpacker::kDeltaMissingExistingFile;
207 345
208 patch_abs_path_ = input_dir.Append( 346 patch_abs_path_ = input_dir.Append(
209 base::FilePath::FromUTF8Unsafe(patch_rel_path)); 347 base::FilePath::FromUTF8Unsafe(patch_rel_path));
210 348
211 return ComponentUnpacker::kNone; 349 return ComponentUnpacker::kNone;
212 } 350 }
213 351
214 ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoRun( 352 void DeltaUpdateOpPatch::DoRun(const ComponentUnpacker::Callback& callback) {
215 ComponentPatcher* patcher, 353 callback_ = callback;
216 int* error) { 354 if (!InProcess()) {
217 *error = 0; 355 host_ = new DeltaUpdateOpPatchHost(scoped_refptr<DeltaUpdateOpPatch>(this));
218 return patcher->Patch(ComponentPatcher::kPatchTypeCourgette, 356 content::BrowserThread::PostTask(
219 input_abs_path_, 357 content::BrowserThread::IO,
220 patch_abs_path_, 358 FROM_HERE,
221 output_abs_path_, 359 base::Bind(&DeltaUpdateOpPatchHost::StartProcess,
222 error); 360 host_,
361 base::Passed(strategy_->GetPatchMessage(input_abs_path_,
362 patch_abs_path_,
363 output_abs_path_))));
364 return;
365 }
366 const int result = strategy_->Patch(input_abs_path_,
367 patch_abs_path_,
368 output_abs_path_);
369 if (result == strategy_->GetSuccessCode())
370 DonePatching(ComponentUnpacker::kNone, 0);
371 else
372 DonePatching(ComponentUnpacker::kDeltaOperationFailure, result);
373 }
374
375 void DeltaUpdateOpPatch::DonePatching(ComponentUnpacker::Error error,
376 int error_code) {
377 host_ = NULL;
378 if (error != ComponentUnpacker::kNone) {
379 error_code += strategy_->GetErrorOffset();
380 }
381 callback_.Run(error, error_code);
382 // The callback is no longer needed - it is best to release it in case it
383 // contains a reference to this object.
384 callback_.Reset();
223 } 385 }
224 386
225 } // namespace component_updater 387 } // namespace component_updater
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698