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" |
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 |
OLD | NEW |