OLD | NEW |
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" | |
11 #include "base/file_util.h" | 10 #include "base/file_util.h" |
12 #include "base/files/memory_mapped_file.h" | 11 #include "base/files/memory_mapped_file.h" |
13 #include "base/json/json_file_value_serializer.h" | 12 #include "base/json/json_file_value_serializer.h" |
14 #include "base/memory/scoped_handle.h" | 13 #include "base/memory/scoped_handle.h" |
15 #include "base/path_service.h" | 14 #include "base/path_service.h" |
16 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
17 #include "chrome/browser/component_updater/component_patcher.h" | 16 #include "chrome/browser/component_updater/component_patcher.h" |
18 #include "chrome/browser/component_updater/component_updater_service.h" | 17 #include "chrome/browser/component_updater/component_updater_service.h" |
19 #include "chrome/common/chrome_utility_messages.h" | |
20 #include "chrome/common/extensions/extension_constants.h" | 18 #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" | |
25 #include "crypto/secure_hash.h" | 19 #include "crypto/secure_hash.h" |
26 #include "crypto/sha2.h" | 20 #include "crypto/sha2.h" |
27 #include "crypto/signature_verifier.h" | 21 #include "crypto/signature_verifier.h" |
28 #include "extensions/common/crx_file.h" | 22 #include "extensions/common/crx_file.h" |
29 #include "ipc/ipc_message_macros.h" | |
30 #include "third_party/zlib/google/zip.h" | 23 #include "third_party/zlib/google/zip.h" |
31 | 24 |
32 using crypto::SecureHash; | 25 using crypto::SecureHash; |
33 | 26 |
34 namespace component_updater { | 27 namespace component_updater { |
35 | 28 |
36 namespace { | 29 namespace { |
37 | 30 |
38 const char kInput[] = "input"; | 31 const char kInput[] = "input"; |
39 const char kOp[] = "op"; | 32 const char kOp[] = "op"; |
40 const char kOutput[] = "output"; | 33 const char kOutput[] = "output"; |
41 const char kPatch[] = "patch"; | 34 const char kPatch[] = "patch"; |
42 const char kSha256[] = "sha256"; | 35 const char kSha256[] = "sha256"; |
43 | 36 |
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 | |
126 } // namespace | 37 } // namespace |
127 | 38 |
128 DeltaUpdateOpPatchStrategy::~DeltaUpdateOpPatchStrategy() { | 39 DeltaUpdateOp* CreateDeltaUpdateOp(base::DictionaryValue* command) { |
129 } | 40 std::string operation; |
130 | 41 if (!command->GetString(kOp, &operation)) |
131 DeltaUpdateOp* CreateDeltaUpdateOp(const std::string& operation) { | 42 return NULL; |
132 if (operation == "copy") { | 43 if (operation == "copy") |
133 return new DeltaUpdateOpCopy(); | 44 return new DeltaUpdateOpCopy(); |
134 } else if (operation == "create") { | 45 else if (operation == "create") |
135 return new DeltaUpdateOpCreate(); | 46 return new DeltaUpdateOpCreate(); |
136 } else if (operation == "bsdiff") { | 47 else if (operation == "bsdiff") |
137 scoped_ptr<DeltaUpdateOpPatchStrategy> strategy(new BsdiffTraits()); | 48 return new DeltaUpdateOpPatchBsdiff(); |
138 return new DeltaUpdateOpPatch(strategy.Pass()); | 49 else if (operation == "courgette") |
139 } else if (operation == "courgette") { | 50 return new DeltaUpdateOpPatchCourgette(); |
140 scoped_ptr<DeltaUpdateOpPatchStrategy> strategy(new CourgetteTraits()); | |
141 return new DeltaUpdateOpPatch(strategy.Pass()); | |
142 } | |
143 return NULL; | 51 return NULL; |
144 } | 52 } |
145 | 53 |
146 DeltaUpdateOp* CreateDeltaUpdateOp(const base::DictionaryValue& command) { | 54 DeltaUpdateOp::DeltaUpdateOp() {} |
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) {} | |
154 | 55 |
155 DeltaUpdateOp::~DeltaUpdateOp() {} | 56 DeltaUpdateOp::~DeltaUpdateOp() {} |
156 | 57 |
157 void DeltaUpdateOp::Run( | 58 ComponentUnpacker::Error DeltaUpdateOp::Run(base::DictionaryValue* command_args, |
158 const base::DictionaryValue* command_args, | 59 const base::FilePath& input_dir, |
159 const base::FilePath& input_dir, | 60 const base::FilePath& unpack_dir, |
160 const base::FilePath& unpack_dir, | 61 ComponentPatcher* patcher, |
161 ComponentInstaller* installer, | 62 ComponentInstaller* installer, |
162 bool in_process, | 63 int* error) { |
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; | |
168 std::string output_rel_path; | 64 std::string output_rel_path; |
169 if (!command_args->GetString(kOutput, &output_rel_path) || | 65 if (!command_args->GetString(kOutput, &output_rel_path) || |
170 !command_args->GetString(kSha256, &output_sha256_)) { | 66 !command_args->GetString(kSha256, &output_sha256_)) |
171 DoneRunning(ComponentUnpacker::kDeltaBadCommands, 0); | 67 return ComponentUnpacker::kDeltaBadCommands; |
172 return; | |
173 } | |
174 | 68 |
175 output_abs_path_ = unpack_dir.Append( | 69 output_abs_path_ = unpack_dir.Append( |
176 base::FilePath::FromUTF8Unsafe(output_rel_path)); | 70 base::FilePath::FromUTF8Unsafe(output_rel_path)); |
177 ComponentUnpacker::Error parse_result = DoParseArguments( | 71 ComponentUnpacker::Error parse_result = DoParseArguments( |
178 command_args, input_dir, installer); | 72 command_args, input_dir, installer); |
179 if (parse_result != ComponentUnpacker::kNone) { | 73 if (parse_result != ComponentUnpacker::kNone) |
180 DoneRunning(parse_result, 0); | 74 return parse_result; |
181 return; | |
182 } | |
183 | 75 |
184 const base::FilePath parent = output_abs_path_.DirName(); | 76 const base::FilePath parent = output_abs_path_.DirName(); |
185 if (!base::DirectoryExists(parent)) { | 77 if (!base::DirectoryExists(parent)) { |
186 if (!base::CreateDirectory(parent)) { | 78 if (!base::CreateDirectory(parent)) |
187 DoneRunning(ComponentUnpacker::kIoError, 0); | 79 return ComponentUnpacker::kIoError; |
188 return; | |
189 } | |
190 } | 80 } |
191 | 81 |
192 DoRun(base::Bind(&DeltaUpdateOp::DoneRunning, | 82 ComponentUnpacker::Error run_result = DoRun(patcher, error); |
193 scoped_refptr<DeltaUpdateOp>(this))); | 83 if (run_result != ComponentUnpacker::kNone) |
194 } | 84 return run_result; |
195 | 85 |
196 void DeltaUpdateOp::DoneRunning(ComponentUnpacker::Error error, | 86 return CheckHash(); |
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(); | |
203 } | 87 } |
204 | 88 |
205 // Uses the hash as a checksum to confirm that the file now residing in the | 89 // Uses the hash as a checksum to confirm that the file now residing in the |
206 // output directory probably has the contents it should. | 90 // output directory probably has the contents it should. |
207 ComponentUnpacker::Error DeltaUpdateOp::CheckHash() { | 91 ComponentUnpacker::Error DeltaUpdateOp::CheckHash() { |
208 std::vector<uint8> expected_hash; | 92 std::vector<uint8> expected_hash; |
209 if (!base::HexStringToBytes(output_sha256_, &expected_hash) || | 93 if (!base::HexStringToBytes(output_sha256_, &expected_hash) || |
210 expected_hash.size() != crypto::kSHA256Length) | 94 expected_hash.size() != crypto::kSHA256Length) |
211 return ComponentUnpacker::kDeltaVerificationFailure; | 95 return ComponentUnpacker::kDeltaVerificationFailure; |
212 | 96 |
213 base::MemoryMappedFile output_file_mmapped; | 97 base::MemoryMappedFile output_file_mmapped; |
214 if (!output_file_mmapped.Initialize(output_abs_path_)) | 98 if (!output_file_mmapped.Initialize(output_abs_path_)) |
215 return ComponentUnpacker::kDeltaVerificationFailure; | 99 return ComponentUnpacker::kDeltaVerificationFailure; |
216 | 100 |
217 uint8 actual_hash[crypto::kSHA256Length] = {0}; | 101 uint8 actual_hash[crypto::kSHA256Length] = {0}; |
218 const scoped_ptr<SecureHash> hasher(SecureHash::Create(SecureHash::SHA256)); | 102 const scoped_ptr<SecureHash> hasher(SecureHash::Create(SecureHash::SHA256)); |
219 hasher->Update(output_file_mmapped.data(), output_file_mmapped.length()); | 103 hasher->Update(output_file_mmapped.data(), output_file_mmapped.length()); |
220 hasher->Finish(actual_hash, sizeof(actual_hash)); | 104 hasher->Finish(actual_hash, sizeof(actual_hash)); |
221 if (memcmp(actual_hash, &expected_hash[0], sizeof(actual_hash))) | 105 if (memcmp(actual_hash, &expected_hash[0], sizeof(actual_hash))) |
222 return ComponentUnpacker::kDeltaVerificationFailure; | 106 return ComponentUnpacker::kDeltaVerificationFailure; |
223 | 107 |
224 return ComponentUnpacker::kNone; | 108 return ComponentUnpacker::kNone; |
225 } | 109 } |
226 | 110 |
227 bool DeltaUpdateOp::InProcess() { | |
228 return in_process_; | |
229 } | |
230 | |
231 DeltaUpdateOpCopy::DeltaUpdateOpCopy() {} | 111 DeltaUpdateOpCopy::DeltaUpdateOpCopy() {} |
232 | 112 |
233 DeltaUpdateOpCopy::~DeltaUpdateOpCopy() {} | |
234 | |
235 ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments( | 113 ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments( |
236 const base::DictionaryValue* command_args, | 114 base::DictionaryValue* command_args, |
237 const base::FilePath& input_dir, | 115 const base::FilePath& input_dir, |
238 ComponentInstaller* installer) { | 116 ComponentInstaller* installer) { |
239 std::string input_rel_path; | 117 std::string input_rel_path; |
240 if (!command_args->GetString(kInput, &input_rel_path)) | 118 if (!command_args->GetString(kInput, &input_rel_path)) |
241 return ComponentUnpacker::kDeltaBadCommands; | 119 return ComponentUnpacker::kDeltaBadCommands; |
242 | 120 |
243 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_)) | 121 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_)) |
244 return ComponentUnpacker::kDeltaMissingExistingFile; | 122 return ComponentUnpacker::kDeltaMissingExistingFile; |
245 | 123 |
246 return ComponentUnpacker::kNone; | 124 return ComponentUnpacker::kNone; |
247 } | 125 } |
248 | 126 |
249 void DeltaUpdateOpCopy::DoRun(const ComponentUnpacker::Callback& callback) { | 127 ComponentUnpacker::Error DeltaUpdateOpCopy::DoRun(ComponentPatcher*, |
| 128 int* error) { |
| 129 *error = 0; |
250 if (!base::CopyFile(input_abs_path_, output_abs_path_)) | 130 if (!base::CopyFile(input_abs_path_, output_abs_path_)) |
251 callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0); | 131 return ComponentUnpacker::kDeltaOperationFailure; |
252 else | 132 |
253 callback.Run(ComponentUnpacker::kNone, 0); | 133 return ComponentUnpacker::kNone; |
254 } | 134 } |
255 | 135 |
256 DeltaUpdateOpCreate::DeltaUpdateOpCreate() {} | 136 DeltaUpdateOpCreate::DeltaUpdateOpCreate() {} |
257 | 137 |
258 DeltaUpdateOpCreate::~DeltaUpdateOpCreate() {} | |
259 | |
260 ComponentUnpacker::Error DeltaUpdateOpCreate::DoParseArguments( | 138 ComponentUnpacker::Error DeltaUpdateOpCreate::DoParseArguments( |
261 const base::DictionaryValue* command_args, | 139 base::DictionaryValue* command_args, |
262 const base::FilePath& input_dir, | 140 const base::FilePath& input_dir, |
263 ComponentInstaller* installer) { | 141 ComponentInstaller* installer) { |
264 std::string patch_rel_path; | 142 std::string patch_rel_path; |
265 if (!command_args->GetString(kPatch, &patch_rel_path)) | 143 if (!command_args->GetString(kPatch, &patch_rel_path)) |
266 return ComponentUnpacker::kDeltaBadCommands; | 144 return ComponentUnpacker::kDeltaBadCommands; |
267 | 145 |
268 patch_abs_path_ = input_dir.Append( | 146 patch_abs_path_ = input_dir.Append( |
269 base::FilePath::FromUTF8Unsafe(patch_rel_path)); | 147 base::FilePath::FromUTF8Unsafe(patch_rel_path)); |
270 | 148 |
271 return ComponentUnpacker::kNone; | 149 return ComponentUnpacker::kNone; |
272 } | 150 } |
273 | 151 |
274 void DeltaUpdateOpCreate::DoRun(const ComponentUnpacker::Callback& callback) { | 152 ComponentUnpacker::Error DeltaUpdateOpCreate::DoRun(ComponentPatcher*, |
| 153 int* error) { |
| 154 *error = 0; |
275 if (!base::Move(patch_abs_path_, output_abs_path_)) | 155 if (!base::Move(patch_abs_path_, output_abs_path_)) |
276 callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0); | 156 return ComponentUnpacker::kDeltaOperationFailure; |
277 else | 157 |
278 callback.Run(ComponentUnpacker::kNone, 0); | 158 return ComponentUnpacker::kNone; |
279 } | 159 } |
280 | 160 |
281 DeltaUpdateOpPatchHost::DeltaUpdateOpPatchHost( | 161 DeltaUpdateOpPatchBsdiff::DeltaUpdateOpPatchBsdiff() {} |
282 scoped_refptr<DeltaUpdateOpPatch> patcher) : patcher_(patcher) { | |
283 } | |
284 | 162 |
285 DeltaUpdateOpPatchHost::~DeltaUpdateOpPatchHost() { | 163 ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoParseArguments( |
286 } | 164 base::DictionaryValue* command_args, |
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 host_ = new DeltaUpdateOpPatchHost(scoped_refptr<DeltaUpdateOpPatch>(this)); | |
329 } | |
330 | |
331 DeltaUpdateOpPatch::~DeltaUpdateOpPatch() { | |
332 } | |
333 | |
334 ComponentUnpacker::Error DeltaUpdateOpPatch::DoParseArguments( | |
335 const base::DictionaryValue* command_args, | |
336 const base::FilePath& input_dir, | 165 const base::FilePath& input_dir, |
337 ComponentInstaller* installer) { | 166 ComponentInstaller* installer) { |
338 std::string patch_rel_path; | 167 std::string patch_rel_path; |
339 std::string input_rel_path; | 168 std::string input_rel_path; |
340 if (!command_args->GetString(kPatch, &patch_rel_path) || | 169 if (!command_args->GetString(kPatch, &patch_rel_path) || |
341 !command_args->GetString(kInput, &input_rel_path)) | 170 !command_args->GetString(kInput, &input_rel_path)) |
342 return ComponentUnpacker::kDeltaBadCommands; | 171 return ComponentUnpacker::kDeltaBadCommands; |
343 | 172 |
344 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_)) | 173 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_)) |
345 return ComponentUnpacker::kDeltaMissingExistingFile; | 174 return ComponentUnpacker::kDeltaMissingExistingFile; |
346 | 175 |
347 patch_abs_path_ = input_dir.Append( | 176 patch_abs_path_ = input_dir.Append( |
348 base::FilePath::FromUTF8Unsafe(patch_rel_path)); | 177 base::FilePath::FromUTF8Unsafe(patch_rel_path)); |
349 | 178 |
350 return ComponentUnpacker::kNone; | 179 return ComponentUnpacker::kNone; |
351 } | 180 } |
352 | 181 |
353 void DeltaUpdateOpPatch::DoRun(const ComponentUnpacker::Callback& callback) { | 182 ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoRun( |
354 callback_ = callback; | 183 ComponentPatcher* patcher, |
355 if (!InProcess()) { | 184 int* error) { |
356 content::BrowserThread::PostTask( | 185 *error = 0; |
357 content::BrowserThread::IO, | 186 return patcher->Patch(ComponentPatcher::kPatchTypeBsdiff, |
358 FROM_HERE, | 187 input_abs_path_, |
359 base::Bind(&DeltaUpdateOpPatchHost::StartProcess, | 188 patch_abs_path_, |
360 host_, | 189 output_abs_path_, |
361 base::Passed(strategy_->GetPatchMessage(input_abs_path_, | 190 error); |
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 } | 191 } |
374 | 192 |
375 void DeltaUpdateOpPatch::DonePatching(ComponentUnpacker::Error error, | 193 DeltaUpdateOpPatchCourgette::DeltaUpdateOpPatchCourgette() {} |
376 int error_code) { | 194 |
377 host_ = NULL; | 195 ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoParseArguments( |
378 if (error != ComponentUnpacker::kNone) { | 196 base::DictionaryValue* command_args, |
379 error_code += strategy_->GetErrorOffset(); | 197 const base::FilePath& input_dir, |
380 } | 198 ComponentInstaller* installer) { |
381 callback_.Run(error, error_code); | 199 std::string patch_rel_path; |
382 // The callback is no longer needed - it is best to release it in case it | 200 std::string input_rel_path; |
383 // contains a reference to this object. | 201 if (!command_args->GetString(kPatch, &patch_rel_path) || |
384 callback_.Reset(); | 202 !command_args->GetString(kInput, &input_rel_path)) |
| 203 return ComponentUnpacker::kDeltaBadCommands; |
| 204 |
| 205 if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_)) |
| 206 return ComponentUnpacker::kDeltaMissingExistingFile; |
| 207 |
| 208 patch_abs_path_ = input_dir.Append( |
| 209 base::FilePath::FromUTF8Unsafe(patch_rel_path)); |
| 210 |
| 211 return ComponentUnpacker::kNone; |
| 212 } |
| 213 |
| 214 ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoRun( |
| 215 ComponentPatcher* patcher, |
| 216 int* error) { |
| 217 *error = 0; |
| 218 return patcher->Patch(ComponentPatcher::kPatchTypeCourgette, |
| 219 input_abs_path_, |
| 220 patch_abs_path_, |
| 221 output_abs_path_, |
| 222 error); |
385 } | 223 } |
386 | 224 |
387 } // namespace component_updater | 225 } // namespace component_updater |
OLD | NEW |