OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/extensions/sandboxed_extension_unpacker.h" | 5 #include "chrome/browser/extensions/sandboxed_extension_unpacker.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 location_(location), creation_flags_(creation_flags) { | 122 location_(location), creation_flags_(creation_flags) { |
123 } | 123 } |
124 | 124 |
125 bool SandboxedExtensionUnpacker::CreateTempDirectory() { | 125 bool SandboxedExtensionUnpacker::CreateTempDirectory() { |
126 CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_identifier_)); | 126 CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_identifier_)); |
127 | 127 |
128 FilePath user_data_temp_dir = extension_file_util::GetUserDataTempDir(); | 128 FilePath user_data_temp_dir = extension_file_util::GetUserDataTempDir(); |
129 if (user_data_temp_dir.empty()) { | 129 if (user_data_temp_dir.empty()) { |
130 ReportFailure( | 130 ReportFailure( |
131 COULD_NOT_GET_TEMP_DIRECTORY, | 131 COULD_NOT_GET_TEMP_DIRECTORY, |
132 l10n_util::GetStringFUTF8( | 132 l10n_util::GetStringFUTF16( |
133 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 133 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
134 ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY"))); | 134 ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY"))); |
135 return false; | 135 return false; |
136 } | 136 } |
137 | 137 |
138 if (!temp_dir_.CreateUniqueTempDirUnderPath(user_data_temp_dir)) { | 138 if (!temp_dir_.CreateUniqueTempDirUnderPath(user_data_temp_dir)) { |
139 ReportFailure( | 139 ReportFailure( |
140 COULD_NOT_CREATE_TEMP_DIRECTORY, | 140 COULD_NOT_CREATE_TEMP_DIRECTORY, |
141 l10n_util::GetStringFUTF8( | 141 l10n_util::GetStringFUTF16( |
142 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 142 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
143 ASCIIToUTF16("COULD_NOT_CREATE_TEMP_DIRECTORY"))); | 143 ASCIIToUTF16("COULD_NOT_CREATE_TEMP_DIRECTORY"))); |
144 return false; | 144 return false; |
145 } | 145 } |
146 | 146 |
147 return true; | 147 return true; |
148 } | 148 } |
149 | 149 |
150 void SandboxedExtensionUnpacker::Start() { | 150 void SandboxedExtensionUnpacker::Start() { |
151 // We assume that we are started on the thread that the client wants us to do | 151 // We assume that we are started on the thread that the client wants us to do |
(...skipping 19 matching lines...) Expand all Loading... |
171 | 171 |
172 // Copy the crx file into our working directory. | 172 // Copy the crx file into our working directory. |
173 FilePath temp_crx_path = temp_dir_.path().Append(crx_path_.BaseName()); | 173 FilePath temp_crx_path = temp_dir_.path().Append(crx_path_.BaseName()); |
174 PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackTempCrxPathLength", | 174 PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackTempCrxPathLength", |
175 temp_crx_path); | 175 temp_crx_path); |
176 | 176 |
177 if (!file_util::CopyFile(crx_path_, temp_crx_path)) { | 177 if (!file_util::CopyFile(crx_path_, temp_crx_path)) { |
178 // Failed to copy extension file to temporary directory. | 178 // Failed to copy extension file to temporary directory. |
179 ReportFailure( | 179 ReportFailure( |
180 FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY, | 180 FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY, |
181 l10n_util::GetStringFUTF8( | 181 l10n_util::GetStringFUTF16( |
182 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 182 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
183 ASCIIToUTF16("FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY"))); | 183 ASCIIToUTF16("FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY"))); |
184 return; | 184 return; |
185 } | 185 } |
186 | 186 |
187 // If we are supposed to use a subprocess, kick off the subprocess. | 187 // If we are supposed to use a subprocess, kick off the subprocess. |
188 // | 188 // |
189 // TODO(asargent) we shouldn't need to do this branch here - instead | 189 // TODO(asargent) we shouldn't need to do this branch here - instead |
190 // UtilityProcessHost should handle it for us. (http://crbug.com/19192) | 190 // UtilityProcessHost should handle it for us. (http://crbug.com/19192) |
191 bool use_utility_process = rdh_ && | 191 bool use_utility_process = rdh_ && |
192 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); | 192 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); |
193 if (use_utility_process) { | 193 if (use_utility_process) { |
194 // The utility process will have access to the directory passed to | 194 // The utility process will have access to the directory passed to |
195 // SandboxedExtensionUnpacker. That directory should not contain a | 195 // SandboxedExtensionUnpacker. That directory should not contain a |
196 // symlink or NTFS reparse point. When the path is used, following | 196 // symlink or NTFS reparse point. When the path is used, following |
197 // the link/reparse point will cause file system access outside the | 197 // the link/reparse point will cause file system access outside the |
198 // sandbox path, and the sandbox will deny the operation. | 198 // sandbox path, and the sandbox will deny the operation. |
199 FilePath link_free_crx_path; | 199 FilePath link_free_crx_path; |
200 if (!file_util::NormalizeFilePath(temp_crx_path, &link_free_crx_path)) { | 200 if (!file_util::NormalizeFilePath(temp_crx_path, &link_free_crx_path)) { |
201 LOG(ERROR) << "Could not get the normalized path of " | 201 LOG(ERROR) << "Could not get the normalized path of " |
202 << temp_crx_path.value(); | 202 << temp_crx_path.value(); |
203 ReportFailure( | 203 ReportFailure( |
204 COULD_NOT_GET_SANDBOX_FRIENDLY_PATH, | 204 COULD_NOT_GET_SANDBOX_FRIENDLY_PATH, |
205 l10n_util::GetStringUTF8(IDS_EXTENSION_UNPACK_FAILED)); | 205 l10n_util::GetStringUTF16(IDS_EXTENSION_UNPACK_FAILED)); |
206 return; | 206 return; |
207 } | 207 } |
208 PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackLinkFreeCrxPathLength", | 208 PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackLinkFreeCrxPathLength", |
209 link_free_crx_path); | 209 link_free_crx_path); |
210 | 210 |
211 BrowserThread::PostTask( | 211 BrowserThread::PostTask( |
212 BrowserThread::IO, FROM_HERE, | 212 BrowserThread::IO, FROM_HERE, |
213 base::Bind( | 213 base::Bind( |
214 &SandboxedExtensionUnpacker::StartProcessOnIOThread, | 214 &SandboxedExtensionUnpacker::StartProcessOnIOThread, |
215 this, | 215 this, |
(...skipping 30 matching lines...) Expand all Loading... |
246 } | 246 } |
247 | 247 |
248 void SandboxedExtensionUnpacker::OnProcessCrashed(int exit_code) { | 248 void SandboxedExtensionUnpacker::OnProcessCrashed(int exit_code) { |
249 // Don't report crashes if they happen after we got a response. | 249 // Don't report crashes if they happen after we got a response. |
250 if (got_response_) | 250 if (got_response_) |
251 return; | 251 return; |
252 | 252 |
253 // Utility process crashed while trying to install. | 253 // Utility process crashed while trying to install. |
254 ReportFailure( | 254 ReportFailure( |
255 UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL, | 255 UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL, |
256 l10n_util::GetStringFUTF8( | 256 l10n_util::GetStringFUTF16( |
257 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 257 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
258 ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL"))); | 258 ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL"))); |
259 } | 259 } |
260 | 260 |
261 void SandboxedExtensionUnpacker::StartProcessOnIOThread( | 261 void SandboxedExtensionUnpacker::StartProcessOnIOThread( |
262 const FilePath& temp_crx_path) { | 262 const FilePath& temp_crx_path) { |
263 UtilityProcessHost* host = new UtilityProcessHost(this, thread_identifier_); | 263 UtilityProcessHost* host = new UtilityProcessHost(this, thread_identifier_); |
264 // Grant the subprocess access to the entire subdir the extension file is | 264 // Grant the subprocess access to the entire subdir the extension file is |
265 // in, so that it can unpack to that dir. | 265 // in, so that it can unpack to that dir. |
266 host->set_exposed_dir(temp_crx_path.DirName()); | 266 host->set_exposed_dir(temp_crx_path.DirName()); |
(...skipping 12 matching lines...) Expand all Loading... |
279 scoped_ptr<DictionaryValue> final_manifest(RewriteManifestFile(manifest)); | 279 scoped_ptr<DictionaryValue> final_manifest(RewriteManifestFile(manifest)); |
280 if (!final_manifest.get()) | 280 if (!final_manifest.get()) |
281 return; | 281 return; |
282 | 282 |
283 // Create an extension object that refers to the temporary location the | 283 // Create an extension object that refers to the temporary location the |
284 // extension was unpacked to. We use this until the extension is finally | 284 // extension was unpacked to. We use this until the extension is finally |
285 // installed. For example, the install UI shows images from inside the | 285 // installed. For example, the install UI shows images from inside the |
286 // extension. | 286 // extension. |
287 | 287 |
288 // Localize manifest now, so confirm UI gets correct extension name. | 288 // Localize manifest now, so confirm UI gets correct extension name. |
289 std::string error; | 289 |
| 290 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing |
| 291 // with string16 |
| 292 std::string utf8_error; |
290 if (!extension_l10n_util::LocalizeExtension(extension_root_, | 293 if (!extension_l10n_util::LocalizeExtension(extension_root_, |
291 final_manifest.get(), | 294 final_manifest.get(), |
292 &error)) { | 295 &utf8_error)) { |
293 ReportFailure( | 296 ReportFailure( |
294 COULD_NOT_LOCALIZE_EXTENSION, | 297 COULD_NOT_LOCALIZE_EXTENSION, |
295 l10n_util::GetStringFUTF8( | 298 l10n_util::GetStringFUTF16( |
296 IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, | 299 IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, |
297 ASCIIToUTF16(error))); | 300 UTF8ToUTF16(utf8_error))); |
298 return; | 301 return; |
299 } | 302 } |
300 | 303 |
301 extension_ = Extension::Create( | 304 extension_ = Extension::Create( |
302 extension_root_, | 305 extension_root_, |
303 location_, | 306 location_, |
304 *final_manifest, | 307 *final_manifest, |
305 Extension::REQUIRE_KEY | creation_flags_, | 308 Extension::REQUIRE_KEY | creation_flags_, |
306 &error); | 309 &utf8_error); |
| 310 |
307 | 311 |
308 if (!extension_.get()) { | 312 if (!extension_.get()) { |
309 ReportFailure( | 313 ReportFailure( |
310 INVALID_MANIFEST, | 314 INVALID_MANIFEST, |
311 std::string("Manifest is invalid: ") + error); | 315 ASCIIToUTF16("Manifest is invalid: " + utf8_error)); |
312 return; | 316 return; |
313 } | 317 } |
314 | 318 |
315 if (!RewriteImageFiles()) | 319 if (!RewriteImageFiles()) |
316 return; | 320 return; |
317 | 321 |
318 if (!RewriteCatalogFiles()) | 322 if (!RewriteCatalogFiles()) |
319 return; | 323 return; |
320 | 324 |
321 ReportSuccess(manifest); | 325 ReportSuccess(manifest); |
322 } | 326 } |
323 | 327 |
324 void SandboxedExtensionUnpacker::OnUnpackExtensionFailed( | 328 void SandboxedExtensionUnpacker::OnUnpackExtensionFailed( |
325 const std::string& error) { | 329 const string16& error) { |
326 CHECK(BrowserThread::CurrentlyOn(thread_identifier_)); | 330 CHECK(BrowserThread::CurrentlyOn(thread_identifier_)); |
327 got_response_ = true; | 331 got_response_ = true; |
328 ReportFailure( | 332 ReportFailure( |
329 UNPACKER_CLIENT_FAILED, | 333 UNPACKER_CLIENT_FAILED, |
330 l10n_util::GetStringFUTF8( | 334 l10n_util::GetStringFUTF16( |
331 IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, | 335 IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, |
332 ASCIIToUTF16(error))); | 336 error)); |
333 } | 337 } |
334 | 338 |
335 bool SandboxedExtensionUnpacker::ValidateSignature() { | 339 bool SandboxedExtensionUnpacker::ValidateSignature() { |
336 ScopedStdioHandle file(file_util::OpenFile(crx_path_, "rb")); | 340 ScopedStdioHandle file(file_util::OpenFile(crx_path_, "rb")); |
337 | 341 |
338 if (!file.get()) { | 342 if (!file.get()) { |
339 // Could not open crx file for reading. | 343 // Could not open crx file for reading. |
340 #if defined (OS_WIN) | 344 #if defined (OS_WIN) |
341 // On windows, get the error code. | 345 // On windows, get the error code. |
342 uint32 error_code = ::GetLastError(); | 346 uint32 error_code = ::GetLastError(); |
343 // TODO(skerner): Use this histogram to understand why so many | 347 // TODO(skerner): Use this histogram to understand why so many |
344 // windows users hit this error. crbug.com/69693 | 348 // windows users hit this error. crbug.com/69693 |
345 | 349 |
346 // Windows errors are unit32s, but all of likely errors are in | 350 // Windows errors are unit32s, but all of likely errors are in |
347 // [1, 1000]. See winerror.h for the meaning of specific values. | 351 // [1, 1000]. See winerror.h for the meaning of specific values. |
348 // Clip errors outside the expected range to a single extra value. | 352 // Clip errors outside the expected range to a single extra value. |
349 // If there are errors in that extra bucket, we will know to expand | 353 // If there are errors in that extra bucket, we will know to expand |
350 // the range. | 354 // the range. |
351 const uint32 kMaxErrorToSend = 1001; | 355 const uint32 kMaxErrorToSend = 1001; |
352 error_code = std::min(error_code, kMaxErrorToSend); | 356 error_code = std::min(error_code, kMaxErrorToSend); |
353 UMA_HISTOGRAM_ENUMERATION("Extensions.ErrorCodeFromCrxOpen", | 357 UMA_HISTOGRAM_ENUMERATION("Extensions.ErrorCodeFromCrxOpen", |
354 error_code, kMaxErrorToSend); | 358 error_code, kMaxErrorToSend); |
355 #endif | 359 #endif |
356 | 360 |
357 ReportFailure( | 361 ReportFailure( |
358 CRX_FILE_NOT_READABLE, | 362 CRX_FILE_NOT_READABLE, |
359 l10n_util::GetStringFUTF8( | 363 l10n_util::GetStringFUTF16( |
360 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 364 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
361 ASCIIToUTF16("CRX_FILE_NOT_READABLE"))); | 365 ASCIIToUTF16("CRX_FILE_NOT_READABLE"))); |
362 return false; | 366 return false; |
363 } | 367 } |
364 | 368 |
365 // Read and verify the header. | 369 // Read and verify the header. |
366 ExtensionHeader header; | 370 ExtensionHeader header; |
367 size_t len; | 371 size_t len; |
368 | 372 |
369 // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it | 373 // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it |
370 // appears that we don't have any endian/alignment aware serialization | 374 // appears that we don't have any endian/alignment aware serialization |
371 // code in the code base. So for now, this assumes that we're running | 375 // code in the code base. So for now, this assumes that we're running |
372 // on a little endian machine with 4 byte alignment. | 376 // on a little endian machine with 4 byte alignment. |
373 len = fread(&header, 1, sizeof(ExtensionHeader), | 377 len = fread(&header, 1, sizeof(ExtensionHeader), |
374 file.get()); | 378 file.get()); |
375 if (len < sizeof(ExtensionHeader)) { | 379 if (len < sizeof(ExtensionHeader)) { |
376 // Invalid crx header | 380 // Invalid crx header |
377 ReportFailure( | 381 ReportFailure( |
378 CRX_HEADER_INVALID, | 382 CRX_HEADER_INVALID, |
379 l10n_util::GetStringFUTF8( | 383 l10n_util::GetStringFUTF16( |
380 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 384 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
381 ASCIIToUTF16("CRX_HEADER_INVALID"))); | 385 ASCIIToUTF16("CRX_HEADER_INVALID"))); |
382 return false; | 386 return false; |
383 } | 387 } |
384 if (strncmp(kExtensionHeaderMagic, header.magic, | 388 if (strncmp(kExtensionHeaderMagic, header.magic, |
385 sizeof(header.magic))) { | 389 sizeof(header.magic))) { |
386 // Bad magic number | 390 // Bad magic number |
387 ReportFailure( | 391 ReportFailure( |
388 CRX_MAGIC_NUMBER_INVALID, | 392 CRX_MAGIC_NUMBER_INVALID, |
389 l10n_util::GetStringFUTF8( | 393 l10n_util::GetStringFUTF16( |
390 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 394 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
391 ASCIIToUTF16("CRX_MAGIC_NUMBER_INVALID"))); | 395 ASCIIToUTF16("CRX_MAGIC_NUMBER_INVALID"))); |
392 return false; | 396 return false; |
393 } | 397 } |
394 if (header.version != kCurrentVersion) { | 398 if (header.version != kCurrentVersion) { |
395 // Bad version numer | 399 // Bad version numer |
396 ReportFailure(CRX_VERSION_NUMBER_INVALID, | 400 ReportFailure(CRX_VERSION_NUMBER_INVALID, |
397 l10n_util::GetStringFUTF8( | 401 l10n_util::GetStringFUTF16( |
398 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 402 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
399 ASCIIToUTF16("CRX_VERSION_NUMBER_INVALID"))); | 403 ASCIIToUTF16("CRX_VERSION_NUMBER_INVALID"))); |
400 return false; | 404 return false; |
401 } | 405 } |
402 if (header.key_size > kMaxPublicKeySize || | 406 if (header.key_size > kMaxPublicKeySize || |
403 header.signature_size > kMaxSignatureSize) { | 407 header.signature_size > kMaxSignatureSize) { |
404 // Excessively large key or signature | 408 // Excessively large key or signature |
405 ReportFailure( | 409 ReportFailure( |
406 CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE, | 410 CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE, |
407 l10n_util::GetStringFUTF8( | 411 l10n_util::GetStringFUTF16( |
408 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 412 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
409 ASCIIToUTF16("CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE"))); | 413 ASCIIToUTF16("CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE"))); |
410 return false; | 414 return false; |
411 } | 415 } |
412 if (header.key_size == 0) { | 416 if (header.key_size == 0) { |
413 // Key length is zero | 417 // Key length is zero |
414 ReportFailure( | 418 ReportFailure( |
415 CRX_ZERO_KEY_LENGTH, | 419 CRX_ZERO_KEY_LENGTH, |
416 l10n_util::GetStringFUTF8( | 420 l10n_util::GetStringFUTF16( |
417 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 421 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
418 ASCIIToUTF16("CRX_ZERO_KEY_LENGTH"))); | 422 ASCIIToUTF16("CRX_ZERO_KEY_LENGTH"))); |
419 return false; | 423 return false; |
420 } | 424 } |
421 if (header.signature_size == 0) { | 425 if (header.signature_size == 0) { |
422 // Signature length is zero | 426 // Signature length is zero |
423 ReportFailure( | 427 ReportFailure( |
424 CRX_ZERO_SIGNATURE_LENGTH, | 428 CRX_ZERO_SIGNATURE_LENGTH, |
425 l10n_util::GetStringFUTF8( | 429 l10n_util::GetStringFUTF16( |
426 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 430 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
427 ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH"))); | 431 ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH"))); |
428 return false; | 432 return false; |
429 } | 433 } |
430 | 434 |
431 std::vector<uint8> key; | 435 std::vector<uint8> key; |
432 key.resize(header.key_size); | 436 key.resize(header.key_size); |
433 len = fread(&key.front(), sizeof(uint8), header.key_size, file.get()); | 437 len = fread(&key.front(), sizeof(uint8), header.key_size, file.get()); |
434 if (len < header.key_size) { | 438 if (len < header.key_size) { |
435 // Invalid public key | 439 // Invalid public key |
436 ReportFailure( | 440 ReportFailure( |
437 CRX_PUBLIC_KEY_INVALID, | 441 CRX_PUBLIC_KEY_INVALID, |
438 l10n_util::GetStringFUTF8( | 442 l10n_util::GetStringFUTF16( |
439 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 443 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
440 ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID"))); | 444 ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID"))); |
441 return false; | 445 return false; |
442 } | 446 } |
443 | 447 |
444 std::vector<uint8> signature; | 448 std::vector<uint8> signature; |
445 signature.resize(header.signature_size); | 449 signature.resize(header.signature_size); |
446 len = fread(&signature.front(), sizeof(uint8), header.signature_size, | 450 len = fread(&signature.front(), sizeof(uint8), header.signature_size, |
447 file.get()); | 451 file.get()); |
448 if (len < header.signature_size) { | 452 if (len < header.signature_size) { |
449 // Invalid signature | 453 // Invalid signature |
450 ReportFailure( | 454 ReportFailure( |
451 CRX_SIGNATURE_INVALID, | 455 CRX_SIGNATURE_INVALID, |
452 l10n_util::GetStringFUTF8( | 456 l10n_util::GetStringFUTF16( |
453 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 457 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
454 ASCIIToUTF16("CRX_SIGNATURE_INVALID"))); | 458 ASCIIToUTF16("CRX_SIGNATURE_INVALID"))); |
455 return false; | 459 return false; |
456 } | 460 } |
457 | 461 |
458 crypto::SignatureVerifier verifier; | 462 crypto::SignatureVerifier verifier; |
459 if (!verifier.VerifyInit(extension_misc::kSignatureAlgorithm, | 463 if (!verifier.VerifyInit(extension_misc::kSignatureAlgorithm, |
460 sizeof(extension_misc::kSignatureAlgorithm), | 464 sizeof(extension_misc::kSignatureAlgorithm), |
461 &signature.front(), | 465 &signature.front(), |
462 signature.size(), | 466 signature.size(), |
463 &key.front(), | 467 &key.front(), |
464 key.size())) { | 468 key.size())) { |
465 // Signature verification initialization failed. This is most likely | 469 // Signature verification initialization failed. This is most likely |
466 // caused by a public key in the wrong format (should encode algorithm). | 470 // caused by a public key in the wrong format (should encode algorithm). |
467 ReportFailure( | 471 ReportFailure( |
468 CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED, | 472 CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED, |
469 l10n_util::GetStringFUTF8( | 473 l10n_util::GetStringFUTF16( |
470 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 474 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
471 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED"))); | 475 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED"))); |
472 return false; | 476 return false; |
473 } | 477 } |
474 | 478 |
475 unsigned char buf[1 << 12]; | 479 unsigned char buf[1 << 12]; |
476 while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0) | 480 while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0) |
477 verifier.VerifyUpdate(buf, len); | 481 verifier.VerifyUpdate(buf, len); |
478 | 482 |
479 if (!verifier.VerifyFinal()) { | 483 if (!verifier.VerifyFinal()) { |
480 // Signature verification failed | 484 // Signature verification failed |
481 ReportFailure( | 485 ReportFailure( |
482 CRX_SIGNATURE_VERIFICATION_FAILED, | 486 CRX_SIGNATURE_VERIFICATION_FAILED, |
483 l10n_util::GetStringFUTF8( | 487 l10n_util::GetStringFUTF16( |
484 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 488 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
485 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED"))); | 489 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED"))); |
486 return false; | 490 return false; |
487 } | 491 } |
488 | 492 |
489 base::Base64Encode(std::string(reinterpret_cast<char*>(&key.front()), | 493 base::Base64Encode(std::string(reinterpret_cast<char*>(&key.front()), |
490 key.size()), &public_key_); | 494 key.size()), &public_key_); |
491 return true; | 495 return true; |
492 } | 496 } |
493 | 497 |
494 void SandboxedExtensionUnpacker::ReportFailure(FailureReason reason, | 498 void SandboxedExtensionUnpacker::ReportFailure(FailureReason reason, |
495 const std::string& error) { | 499 const string16& error) { |
496 UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", | 500 UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", |
497 reason, NUM_FAILURE_REASONS); | 501 reason, NUM_FAILURE_REASONS); |
498 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackFailureTime", | 502 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackFailureTime", |
499 base::TimeTicks::Now() - unpack_start_time_); | 503 base::TimeTicks::Now() - unpack_start_time_); |
500 | 504 |
501 client_->OnUnpackFailure(error); | 505 client_->OnUnpackFailure(error); |
502 } | 506 } |
503 | 507 |
504 void SandboxedExtensionUnpacker::ReportSuccess( | 508 void SandboxedExtensionUnpacker::ReportSuccess( |
505 const DictionaryValue& original_manifest) { | 509 const DictionaryValue& original_manifest) { |
(...skipping 18 matching lines...) Expand all Loading... |
524 scoped_ptr<DictionaryValue> final_manifest(manifest.DeepCopy()); | 528 scoped_ptr<DictionaryValue> final_manifest(manifest.DeepCopy()); |
525 final_manifest->SetString(extension_manifest_keys::kPublicKey, public_key_); | 529 final_manifest->SetString(extension_manifest_keys::kPublicKey, public_key_); |
526 | 530 |
527 std::string manifest_json; | 531 std::string manifest_json; |
528 JSONStringValueSerializer serializer(&manifest_json); | 532 JSONStringValueSerializer serializer(&manifest_json); |
529 serializer.set_pretty_print(true); | 533 serializer.set_pretty_print(true); |
530 if (!serializer.Serialize(*final_manifest)) { | 534 if (!serializer.Serialize(*final_manifest)) { |
531 // Error serializing manifest.json. | 535 // Error serializing manifest.json. |
532 ReportFailure( | 536 ReportFailure( |
533 ERROR_SERIALIZING_MANIFEST_JSON, | 537 ERROR_SERIALIZING_MANIFEST_JSON, |
534 l10n_util::GetStringFUTF8( | 538 l10n_util::GetStringFUTF16( |
535 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 539 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
536 ASCIIToUTF16("ERROR_SERIALIZING_MANIFEST_JSON"))); | 540 ASCIIToUTF16("ERROR_SERIALIZING_MANIFEST_JSON"))); |
537 return NULL; | 541 return NULL; |
538 } | 542 } |
539 | 543 |
540 FilePath manifest_path = | 544 FilePath manifest_path = |
541 extension_root_.Append(Extension::kManifestFilename); | 545 extension_root_.Append(Extension::kManifestFilename); |
542 if (!file_util::WriteFile(manifest_path, | 546 if (!file_util::WriteFile(manifest_path, |
543 manifest_json.data(), manifest_json.size())) { | 547 manifest_json.data(), manifest_json.size())) { |
544 // Error saving manifest.json. | 548 // Error saving manifest.json. |
545 ReportFailure( | 549 ReportFailure( |
546 ERROR_SAVING_MANIFEST_JSON, | 550 ERROR_SAVING_MANIFEST_JSON, |
547 l10n_util::GetStringFUTF8( | 551 l10n_util::GetStringFUTF16( |
548 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 552 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
549 ASCIIToUTF16("ERROR_SAVING_MANIFEST_JSON"))); | 553 ASCIIToUTF16("ERROR_SAVING_MANIFEST_JSON"))); |
550 return NULL; | 554 return NULL; |
551 } | 555 } |
552 | 556 |
553 return final_manifest.release(); | 557 return final_manifest.release(); |
554 } | 558 } |
555 | 559 |
556 bool SandboxedExtensionUnpacker::RewriteImageFiles() { | 560 bool SandboxedExtensionUnpacker::RewriteImageFiles() { |
557 ExtensionUnpacker::DecodedImages images; | 561 ExtensionUnpacker::DecodedImages images; |
558 if (!ExtensionUnpacker::ReadImagesFromFile(temp_dir_.path(), &images)) { | 562 if (!ExtensionUnpacker::ReadImagesFromFile(temp_dir_.path(), &images)) { |
559 // Couldn't read image data from disk. | 563 // Couldn't read image data from disk. |
560 ReportFailure( | 564 ReportFailure( |
561 COULD_NOT_READ_IMAGE_DATA_FROM_DISK, | 565 COULD_NOT_READ_IMAGE_DATA_FROM_DISK, |
562 l10n_util::GetStringFUTF8( | 566 l10n_util::GetStringFUTF16( |
563 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 567 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
564 ASCIIToUTF16("COULD_NOT_READ_IMAGE_DATA_FROM_DISK"))); | 568 ASCIIToUTF16("COULD_NOT_READ_IMAGE_DATA_FROM_DISK"))); |
565 return false; | 569 return false; |
566 } | 570 } |
567 | 571 |
568 // Delete any images that may be used by the browser. We're going to write | 572 // Delete any images that may be used by the browser. We're going to write |
569 // out our own versions of the parsed images, and we want to make sure the | 573 // out our own versions of the parsed images, and we want to make sure the |
570 // originals are gone for good. | 574 // originals are gone for good. |
571 std::set<FilePath> image_paths = extension_->GetBrowserImages(); | 575 std::set<FilePath> image_paths = extension_->GetBrowserImages(); |
572 if (image_paths.size() != images.size()) { | 576 if (image_paths.size() != images.size()) { |
573 // Decoded images don't match what's in the manifest. | 577 // Decoded images don't match what's in the manifest. |
574 ReportFailure( | 578 ReportFailure( |
575 DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST, | 579 DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST, |
576 l10n_util::GetStringFUTF8( | 580 l10n_util::GetStringFUTF16( |
577 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 581 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
578 ASCIIToUTF16("DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST"))); | 582 ASCIIToUTF16("DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST"))); |
579 return false; | 583 return false; |
580 } | 584 } |
581 | 585 |
582 for (std::set<FilePath>::iterator it = image_paths.begin(); | 586 for (std::set<FilePath>::iterator it = image_paths.begin(); |
583 it != image_paths.end(); ++it) { | 587 it != image_paths.end(); ++it) { |
584 FilePath path = *it; | 588 FilePath path = *it; |
585 if (path.IsAbsolute() || path.ReferencesParent()) { | 589 if (path.IsAbsolute() || path.ReferencesParent()) { |
586 // Invalid path for browser image. | 590 // Invalid path for browser image. |
587 ReportFailure( | 591 ReportFailure( |
588 INVALID_PATH_FOR_BROWSER_IMAGE, | 592 INVALID_PATH_FOR_BROWSER_IMAGE, |
589 l10n_util::GetStringFUTF8( | 593 l10n_util::GetStringFUTF16( |
590 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 594 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
591 ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE"))); | 595 ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE"))); |
592 return false; | 596 return false; |
593 } | 597 } |
594 if (!file_util::Delete(extension_root_.Append(path), false)) { | 598 if (!file_util::Delete(extension_root_.Append(path), false)) { |
595 // Error removing old image file. | 599 // Error removing old image file. |
596 ReportFailure( | 600 ReportFailure( |
597 ERROR_REMOVING_OLD_IMAGE_FILE, | 601 ERROR_REMOVING_OLD_IMAGE_FILE, |
598 l10n_util::GetStringFUTF8( | 602 l10n_util::GetStringFUTF16( |
599 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 603 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
600 ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE"))); | 604 ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE"))); |
601 return false; | 605 return false; |
602 } | 606 } |
603 } | 607 } |
604 | 608 |
605 // Write our parsed images back to disk as well. | 609 // Write our parsed images back to disk as well. |
606 for (size_t i = 0; i < images.size(); ++i) { | 610 for (size_t i = 0; i < images.size(); ++i) { |
607 const SkBitmap& image = images[i].a; | 611 const SkBitmap& image = images[i].a; |
608 FilePath path_suffix = images[i].b; | 612 FilePath path_suffix = images[i].b; |
609 if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) { | 613 if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) { |
610 // Invalid path for bitmap image. | 614 // Invalid path for bitmap image. |
611 ReportFailure( | 615 ReportFailure( |
612 INVALID_PATH_FOR_BITMAP_IMAGE, | 616 INVALID_PATH_FOR_BITMAP_IMAGE, |
613 l10n_util::GetStringFUTF8( | 617 l10n_util::GetStringFUTF16( |
614 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 618 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
615 ASCIIToUTF16("INVALID_PATH_FOR_BITMAP_IMAGE"))); | 619 ASCIIToUTF16("INVALID_PATH_FOR_BITMAP_IMAGE"))); |
616 return false; | 620 return false; |
617 } | 621 } |
618 FilePath path = extension_root_.Append(path_suffix); | 622 FilePath path = extension_root_.Append(path_suffix); |
619 | 623 |
620 std::vector<unsigned char> image_data; | 624 std::vector<unsigned char> image_data; |
621 // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even | 625 // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even |
622 // though they may originally be .jpg, etc. Figure something out. | 626 // though they may originally be .jpg, etc. Figure something out. |
623 // http://code.google.com/p/chromium/issues/detail?id=12459 | 627 // http://code.google.com/p/chromium/issues/detail?id=12459 |
624 if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) { | 628 if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) { |
625 // Error re-encoding theme image. | 629 // Error re-encoding theme image. |
626 ReportFailure( | 630 ReportFailure( |
627 ERROR_RE_ENCODING_THEME_IMAGE, | 631 ERROR_RE_ENCODING_THEME_IMAGE, |
628 l10n_util::GetStringFUTF8( | 632 l10n_util::GetStringFUTF16( |
629 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 633 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
630 ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE"))); | 634 ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE"))); |
631 return false; | 635 return false; |
632 } | 636 } |
633 | 637 |
634 // Note: we're overwriting existing files that the utility process wrote, | 638 // Note: we're overwriting existing files that the utility process wrote, |
635 // so we can be sure the directory exists. | 639 // so we can be sure the directory exists. |
636 const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]); | 640 const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]); |
637 if (!file_util::WriteFile(path, image_data_ptr, image_data.size())) { | 641 if (!file_util::WriteFile(path, image_data_ptr, image_data.size())) { |
638 // Error saving theme image. | 642 // Error saving theme image. |
639 ReportFailure( | 643 ReportFailure( |
640 ERROR_SAVING_THEME_IMAGE, | 644 ERROR_SAVING_THEME_IMAGE, |
641 l10n_util::GetStringFUTF8( | 645 l10n_util::GetStringFUTF16( |
642 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 646 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
643 ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE"))); | 647 ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE"))); |
644 return false; | 648 return false; |
645 } | 649 } |
646 } | 650 } |
647 | 651 |
648 return true; | 652 return true; |
649 } | 653 } |
650 | 654 |
651 bool SandboxedExtensionUnpacker::RewriteCatalogFiles() { | 655 bool SandboxedExtensionUnpacker::RewriteCatalogFiles() { |
652 DictionaryValue catalogs; | 656 DictionaryValue catalogs; |
653 if (!ExtensionUnpacker::ReadMessageCatalogsFromFile(temp_dir_.path(), | 657 if (!ExtensionUnpacker::ReadMessageCatalogsFromFile(temp_dir_.path(), |
654 &catalogs)) { | 658 &catalogs)) { |
655 // Could not read catalog data from disk. | 659 // Could not read catalog data from disk. |
656 ReportFailure( | 660 ReportFailure( |
657 COULD_NOT_READ_CATALOG_DATA_FROM_DISK, | 661 COULD_NOT_READ_CATALOG_DATA_FROM_DISK, |
658 l10n_util::GetStringFUTF8( | 662 l10n_util::GetStringFUTF16( |
659 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 663 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
660 ASCIIToUTF16("COULD_NOT_READ_CATALOG_DATA_FROM_DISK"))); | 664 ASCIIToUTF16("COULD_NOT_READ_CATALOG_DATA_FROM_DISK"))); |
661 return false; | 665 return false; |
662 } | 666 } |
663 | 667 |
664 // Write our parsed catalogs back to disk. | 668 // Write our parsed catalogs back to disk. |
665 for (DictionaryValue::key_iterator key_it = catalogs.begin_keys(); | 669 for (DictionaryValue::key_iterator key_it = catalogs.begin_keys(); |
666 key_it != catalogs.end_keys(); ++key_it) { | 670 key_it != catalogs.end_keys(); ++key_it) { |
667 DictionaryValue* catalog; | 671 DictionaryValue* catalog; |
668 if (!catalogs.GetDictionaryWithoutPathExpansion(*key_it, &catalog)) { | 672 if (!catalogs.GetDictionaryWithoutPathExpansion(*key_it, &catalog)) { |
669 // Invalid catalog data. | 673 // Invalid catalog data. |
670 ReportFailure( | 674 ReportFailure( |
671 INVALID_CATALOG_DATA, | 675 INVALID_CATALOG_DATA, |
672 l10n_util::GetStringFUTF8( | 676 l10n_util::GetStringFUTF16( |
673 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 677 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
674 ASCIIToUTF16("INVALID_CATALOG_DATA"))); | 678 ASCIIToUTF16("INVALID_CATALOG_DATA"))); |
675 return false; | 679 return false; |
676 } | 680 } |
677 | 681 |
678 // TODO(viettrungluu): Fix the |FilePath::FromWStringHack(UTF8ToWide())| | 682 // TODO(viettrungluu): Fix the |FilePath::FromWStringHack(UTF8ToWide())| |
679 // hack and remove the corresponding #include. | 683 // hack and remove the corresponding #include. |
680 FilePath relative_path = FilePath::FromWStringHack(UTF8ToWide(*key_it)); | 684 FilePath relative_path = FilePath::FromWStringHack(UTF8ToWide(*key_it)); |
681 relative_path = relative_path.Append(Extension::kMessagesFilename); | 685 relative_path = relative_path.Append(Extension::kMessagesFilename); |
682 if (relative_path.IsAbsolute() || relative_path.ReferencesParent()) { | 686 if (relative_path.IsAbsolute() || relative_path.ReferencesParent()) { |
683 // Invalid path for catalog. | 687 // Invalid path for catalog. |
684 ReportFailure( | 688 ReportFailure( |
685 INVALID_PATH_FOR_CATALOG, | 689 INVALID_PATH_FOR_CATALOG, |
686 l10n_util::GetStringFUTF8( | 690 l10n_util::GetStringFUTF16( |
687 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 691 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
688 ASCIIToUTF16("INVALID_PATH_FOR_CATALOG"))); | 692 ASCIIToUTF16("INVALID_PATH_FOR_CATALOG"))); |
689 return false; | 693 return false; |
690 } | 694 } |
691 FilePath path = extension_root_.Append(relative_path); | 695 FilePath path = extension_root_.Append(relative_path); |
692 | 696 |
693 std::string catalog_json; | 697 std::string catalog_json; |
694 JSONStringValueSerializer serializer(&catalog_json); | 698 JSONStringValueSerializer serializer(&catalog_json); |
695 serializer.set_pretty_print(true); | 699 serializer.set_pretty_print(true); |
696 if (!serializer.Serialize(*catalog)) { | 700 if (!serializer.Serialize(*catalog)) { |
697 // Error serializing catalog. | 701 // Error serializing catalog. |
698 ReportFailure( | 702 ReportFailure( |
699 ERROR_SERIALIZING_CATALOG, | 703 ERROR_SERIALIZING_CATALOG, |
700 l10n_util::GetStringFUTF8( | 704 l10n_util::GetStringFUTF16( |
701 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 705 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
702 ASCIIToUTF16("ERROR_SERIALIZING_CATALOG"))); | 706 ASCIIToUTF16("ERROR_SERIALIZING_CATALOG"))); |
703 return false; | 707 return false; |
704 } | 708 } |
705 | 709 |
706 // Note: we're overwriting existing files that the utility process read, | 710 // Note: we're overwriting existing files that the utility process read, |
707 // so we can be sure the directory exists. | 711 // so we can be sure the directory exists. |
708 if (!file_util::WriteFile(path, | 712 if (!file_util::WriteFile(path, |
709 catalog_json.c_str(), | 713 catalog_json.c_str(), |
710 catalog_json.size())) { | 714 catalog_json.size())) { |
711 // Error saving catalog. | 715 // Error saving catalog. |
712 ReportFailure( | 716 ReportFailure( |
713 ERROR_SAVING_CATALOG, | 717 ERROR_SAVING_CATALOG, |
714 l10n_util::GetStringFUTF8( | 718 l10n_util::GetStringFUTF16( |
715 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 719 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
716 ASCIIToUTF16("ERROR_SAVING_CATALOG"))); | 720 ASCIIToUTF16("ERROR_SAVING_CATALOG"))); |
717 return false; | 721 return false; |
718 } | 722 } |
719 } | 723 } |
720 | 724 |
721 return true; | 725 return true; |
722 } | 726 } |
OLD | NEW |