Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "extensions/browser/sandboxed_unpacker.h" | 5 #include "extensions/browser/sandboxed_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" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 13 #include "base/files/file_util_proxy.h" | 13 #include "base/files/file_util_proxy.h" |
| 14 #include "base/files/scoped_file.h" | 14 #include "base/files/scoped_file.h" |
| 15 #include "base/json/json_string_value_serializer.h" | 15 #include "base/json/json_string_value_serializer.h" |
| 16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 18 #include "base/numerics/safe_conversions.h" | 18 #include "base/numerics/safe_conversions.h" |
| 19 #include "base/path_service.h" | 19 #include "base/path_service.h" |
| 20 #include "base/sequenced_task_runner.h" | 20 #include "base/sequenced_task_runner.h" |
| 21 #include "base/strings/string_number_conversions.h" | |
| 21 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
| 22 #include "base/threading/sequenced_worker_pool.h" | 23 #include "base/threading/sequenced_worker_pool.h" |
| 23 #include "components/crx_file/constants.h" | 24 #include "components/crx_file/constants.h" |
| 24 #include "components/crx_file/crx_file.h" | 25 #include "components/crx_file/crx_file.h" |
| 25 #include "components/crx_file/id_util.h" | 26 #include "components/crx_file/id_util.h" |
| 26 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
| 27 #include "content/public/browser/utility_process_host.h" | 28 #include "content/public/browser/utility_process_host.h" |
| 28 #include "content/public/common/common_param_traits.h" | 29 #include "content/public/common/common_param_traits.h" |
| 30 #include "crypto/secure_hash.h" | |
| 31 #include "crypto/sha2.h" | |
| 29 #include "crypto/signature_verifier.h" | 32 #include "crypto/signature_verifier.h" |
| 30 #include "extensions/common/constants.h" | 33 #include "extensions/common/constants.h" |
| 31 #include "extensions/common/extension.h" | 34 #include "extensions/common/extension.h" |
| 32 #include "extensions/common/extension_l10n_util.h" | 35 #include "extensions/common/extension_l10n_util.h" |
| 33 #include "extensions/common/extension_utility_messages.h" | 36 #include "extensions/common/extension_utility_messages.h" |
| 34 #include "extensions/common/extensions_client.h" | 37 #include "extensions/common/extensions_client.h" |
| 35 #include "extensions/common/file_util.h" | 38 #include "extensions/common/file_util.h" |
| 36 #include "extensions/common/manifest_constants.h" | 39 #include "extensions/common/manifest_constants.h" |
| 37 #include "extensions/common/manifest_handlers/icons_handler.h" | 40 #include "extensions/common/manifest_handlers/icons_handler.h" |
| 41 #include "extensions/common/switches.h" | |
| 38 #include "grit/extensions_strings.h" | 42 #include "grit/extensions_strings.h" |
| 39 #include "third_party/skia/include/core/SkBitmap.h" | 43 #include "third_party/skia/include/core/SkBitmap.h" |
| 40 #include "ui/base/l10n/l10n_util.h" | 44 #include "ui/base/l10n/l10n_util.h" |
| 41 #include "ui/gfx/codec/png_codec.h" | 45 #include "ui/gfx/codec/png_codec.h" |
| 42 | 46 |
| 43 using base::ASCIIToUTF16; | 47 using base::ASCIIToUTF16; |
| 44 using content::BrowserThread; | 48 using content::BrowserThread; |
| 45 using content::UtilityProcessHost; | 49 using content::UtilityProcessHost; |
| 46 using crx_file::CrxFile; | 50 using crx_file::CrxFile; |
| 47 | 51 |
| 48 // The following macro makes histograms that record the length of paths | 52 // The following macro makes histograms that record the length of paths |
| 49 // in this file much easier to read. | 53 // in this file much easier to read. |
| 50 // Windows has a short max path length. If the path length to a | 54 // Windows has a short max path length. If the path length to a |
| 51 // file being unpacked from a CRX exceeds the max length, we might | 55 // file being unpacked from a CRX exceeds the max length, we might |
| 52 // fail to install. To see if this is happening, see how long the | 56 // fail to install. To see if this is happening, see how long the |
| 53 // path to the temp unpack directory is. See crbug.com/69693 . | 57 // path to the temp unpack directory is. See crbug.com/69693 . |
| 54 #define PATH_LENGTH_HISTOGRAM(name, path) \ | 58 #define PATH_LENGTH_HISTOGRAM(name, path) \ |
| 55 UMA_HISTOGRAM_CUSTOM_COUNTS(name, path.value().length(), 0, 500, 100) | 59 UMA_HISTOGRAM_CUSTOM_COUNTS(name, path.value().length(), 0, 500, 100) |
| 56 | 60 |
| 57 // Record a rate (kB per second) at which extensions are unpacked. | 61 // Record a rate (kB per second) at which extensions are unpacked. |
| 58 // Range from 1kB/s to 100mB/s. | 62 // Range from 1kB/s to 100mB/s. |
| 59 #define UNPACK_RATE_HISTOGRAM(name, rate) \ | 63 #define UNPACK_RATE_HISTOGRAM(name, rate) \ |
| 60 UMA_HISTOGRAM_CUSTOM_COUNTS(name, rate, 1, 100000, 100); | 64 UMA_HISTOGRAM_CUSTOM_COUNTS(name, rate, 1, 100000, 100); |
| 61 | 65 |
| 66 // Record if the .crx hash sum is the same as in the updater manifest. | |
| 67 #define CRX_HASH_CHECK_HISTOGRAM(name, success) \ | |
|
Ilya Sherman
2015/02/03 21:40:29
Why do you need a wrapper macro?
| |
| 68 UMA_HISTOGRAM_BOOLEAN(name, success) | |
| 69 | |
| 62 namespace extensions { | 70 namespace extensions { |
| 63 namespace { | 71 namespace { |
| 64 | 72 |
| 65 void RecordSuccessfulUnpackTimeHistograms(const base::FilePath& crx_path, | 73 void RecordSuccessfulUnpackTimeHistograms(const base::FilePath& crx_path, |
| 66 const base::TimeDelta unpack_time) { | 74 const base::TimeDelta unpack_time) { |
| 67 const int64 kBytesPerKb = 1024; | 75 const int64 kBytesPerKb = 1024; |
| 68 const int64 kBytesPerMb = 1024 * 1024; | 76 const int64 kBytesPerMb = 1024 * 1024; |
| 69 | 77 |
| 70 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackSuccessTime", unpack_time); | 78 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackSuccessTime", unpack_time); |
| 71 | 79 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 return false; | 210 return false; |
| 203 | 211 |
| 204 IPC::Message pickle(file_str.data(), file_str.size()); | 212 IPC::Message pickle(file_str.data(), file_str.size()); |
| 205 PickleIterator iter(pickle); | 213 PickleIterator iter(pickle); |
| 206 return IPC::ReadParam(&pickle, &iter, catalogs); | 214 return IPC::ReadParam(&pickle, &iter, catalogs); |
| 207 } | 215 } |
| 208 | 216 |
| 209 } // namespace | 217 } // namespace |
| 210 | 218 |
| 211 SandboxedUnpacker::SandboxedUnpacker( | 219 SandboxedUnpacker::SandboxedUnpacker( |
| 212 const base::FilePath& crx_path, | 220 const CRXFileInfo& file, |
| 213 Manifest::Location location, | 221 Manifest::Location location, |
| 214 int creation_flags, | 222 int creation_flags, |
| 215 const base::FilePath& extensions_dir, | 223 const base::FilePath& extensions_dir, |
| 216 const scoped_refptr<base::SequencedTaskRunner>& unpacker_io_task_runner, | 224 const scoped_refptr<base::SequencedTaskRunner>& unpacker_io_task_runner, |
| 217 SandboxedUnpackerClient* client) | 225 SandboxedUnpackerClient* client) |
| 218 : crx_path_(crx_path), | 226 : crx_path_(file.path), |
| 227 package_hash_(file.hash), | |
| 228 check_crx_hash_(false), | |
| 219 client_(client), | 229 client_(client), |
| 220 extensions_dir_(extensions_dir), | 230 extensions_dir_(extensions_dir), |
| 221 got_response_(false), | 231 got_response_(false), |
| 222 location_(location), | 232 location_(location), |
| 223 creation_flags_(creation_flags), | 233 creation_flags_(creation_flags), |
| 224 unpacker_io_task_runner_(unpacker_io_task_runner) { | 234 unpacker_io_task_runner_(unpacker_io_task_runner) { |
| 235 if (!package_hash_.empty()) { | |
| 236 check_crx_hash_ = base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 237 extensions::switches::kEnableCrxHashCheck); | |
| 238 } | |
| 225 } | 239 } |
| 226 | 240 |
| 227 bool SandboxedUnpacker::CreateTempDirectory() { | 241 bool SandboxedUnpacker::CreateTempDirectory() { |
| 228 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); | 242 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); |
| 229 | 243 |
| 230 base::FilePath temp_dir; | 244 base::FilePath temp_dir; |
| 231 if (!FindWritableTempLocation(extensions_dir_, &temp_dir)) { | 245 if (!FindWritableTempLocation(extensions_dir_, &temp_dir)) { |
| 232 ReportFailure(COULD_NOT_GET_TEMP_DIRECTORY, | 246 ReportFailure(COULD_NOT_GET_TEMP_DIRECTORY, |
| 233 l10n_util::GetStringFUTF16( | 247 l10n_util::GetStringFUTF16( |
| 234 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 248 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 } | 409 } |
| 396 | 410 |
| 397 void SandboxedUnpacker::OnUnpackExtensionFailed(const base::string16& error) { | 411 void SandboxedUnpacker::OnUnpackExtensionFailed(const base::string16& error) { |
| 398 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); | 412 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); |
| 399 got_response_ = true; | 413 got_response_ = true; |
| 400 ReportFailure( | 414 ReportFailure( |
| 401 UNPACKER_CLIENT_FAILED, | 415 UNPACKER_CLIENT_FAILED, |
| 402 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, error)); | 416 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, error)); |
| 403 } | 417 } |
| 404 | 418 |
| 419 static size_t ReadAndHash(void* ptr, | |
| 420 size_t size, | |
| 421 size_t nmemb, | |
| 422 FILE* stream, | |
| 423 scoped_ptr<crypto::SecureHash>& hash) { | |
| 424 size_t len = fread(ptr, size, nmemb, stream); | |
| 425 if (len > 0 && hash) { | |
| 426 hash->Update(ptr, len * size); | |
| 427 } | |
| 428 return len; | |
| 429 } | |
| 430 | |
| 431 bool SandboxedUnpacker::FinalizeHash(scoped_ptr<crypto::SecureHash>& hash) { | |
| 432 if (hash) { | |
| 433 uint8 output[crypto::kSHA256Length]; | |
| 434 hash->Finish(output, sizeof(output)); | |
| 435 if (base::StringToLowerASCII(base::HexEncode(output, sizeof(output))) != | |
| 436 package_hash_) { | |
| 437 // Package hash verification failed | |
| 438 CRX_HASH_CHECK_HISTOGRAM("Extensions.SandboxUnpackHashCheck", false); | |
| 439 if (check_crx_hash_) { | |
| 440 std::string name = crx_path_.BaseName().AsUTF8Unsafe(); | |
| 441 LOG(ERROR) << "Hash check failed for extension: " << name; | |
| 442 ReportFailure(CRX_HASH_VERIFICATION_FAILED, | |
| 443 l10n_util::GetStringFUTF16( | |
| 444 IDS_EXTENSION_PACKAGE_ERROR_CODE, | |
| 445 ASCIIToUTF16("CRX_HASH_VERIFICATION_FAILED"))); | |
| 446 return false; | |
| 447 } | |
| 448 } else { | |
| 449 CRX_HASH_CHECK_HISTOGRAM("Extensions.SandboxUnpackHashCheck", true); | |
|
Ilya Sherman
2015/02/03 21:40:29
I'd recommend having a single code path per histog
| |
| 450 } | |
| 451 } | |
| 452 | |
| 453 return true; | |
| 454 } | |
| 455 | |
| 405 bool SandboxedUnpacker::ValidateSignature() { | 456 bool SandboxedUnpacker::ValidateSignature() { |
| 406 base::ScopedFILE file(base::OpenFile(crx_path_, "rb")); | 457 base::ScopedFILE file(base::OpenFile(crx_path_, "rb")); |
| 407 | 458 |
| 459 scoped_ptr<crypto::SecureHash> hash; | |
| 460 | |
| 461 if (!package_hash_.empty()) { | |
| 462 hash.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | |
| 463 } | |
| 464 | |
| 408 if (!file.get()) { | 465 if (!file.get()) { |
| 409 // Could not open crx file for reading. | 466 // Could not open crx file for reading. |
| 410 #if defined(OS_WIN) | 467 #if defined(OS_WIN) |
| 411 // On windows, get the error code. | 468 // On windows, get the error code. |
| 412 uint32 error_code = ::GetLastError(); | 469 uint32 error_code = ::GetLastError(); |
| 413 // TODO(skerner): Use this histogram to understand why so many | 470 // TODO(skerner): Use this histogram to understand why so many |
| 414 // windows users hit this error. crbug.com/69693 | 471 // windows users hit this error. crbug.com/69693 |
| 415 | 472 |
| 416 // Windows errors are unit32s, but all of likely errors are in | 473 // Windows errors are unit32s, but all of likely errors are in |
| 417 // [1, 1000]. See winerror.h for the meaning of specific values. | 474 // [1, 1000]. See winerror.h for the meaning of specific values. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 430 ASCIIToUTF16("CRX_FILE_NOT_READABLE"))); | 487 ASCIIToUTF16("CRX_FILE_NOT_READABLE"))); |
| 431 return false; | 488 return false; |
| 432 } | 489 } |
| 433 | 490 |
| 434 // Read and verify the header. | 491 // Read and verify the header. |
| 435 // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it | 492 // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it |
| 436 // appears that we don't have any endian/alignment aware serialization | 493 // appears that we don't have any endian/alignment aware serialization |
| 437 // code in the code base. So for now, this assumes that we're running | 494 // code in the code base. So for now, this assumes that we're running |
| 438 // on a little endian machine with 4 byte alignment. | 495 // on a little endian machine with 4 byte alignment. |
| 439 CrxFile::Header header; | 496 CrxFile::Header header; |
| 440 size_t len = fread(&header, 1, sizeof(header), file.get()); | 497 size_t len = ReadAndHash(&header, 1, sizeof(header), file.get(), hash); |
| 441 if (len < sizeof(header)) { | 498 if (len < sizeof(header)) { |
| 442 // Invalid crx header | 499 // Invalid crx header |
| 443 ReportFailure(CRX_HEADER_INVALID, l10n_util::GetStringFUTF16( | 500 ReportFailure(CRX_HEADER_INVALID, l10n_util::GetStringFUTF16( |
| 444 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 501 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
| 445 ASCIIToUTF16("CRX_HEADER_INVALID"))); | 502 ASCIIToUTF16("CRX_HEADER_INVALID"))); |
| 446 return false; | 503 return false; |
| 447 } | 504 } |
| 448 | 505 |
| 449 CrxFile::Error error; | 506 CrxFile::Error error; |
| 450 scoped_ptr<CrxFile> crx(CrxFile::Parse(header, &error)); | 507 scoped_ptr<CrxFile> crx(CrxFile::Parse(header, &error)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 485 l10n_util::GetStringFUTF16( | 542 l10n_util::GetStringFUTF16( |
| 486 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 543 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
| 487 ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH"))); | 544 ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH"))); |
| 488 break; | 545 break; |
| 489 } | 546 } |
| 490 return false; | 547 return false; |
| 491 } | 548 } |
| 492 | 549 |
| 493 std::vector<uint8> key; | 550 std::vector<uint8> key; |
| 494 key.resize(header.key_size); | 551 key.resize(header.key_size); |
| 495 len = fread(&key.front(), sizeof(uint8), header.key_size, file.get()); | 552 len = ReadAndHash(&key.front(), sizeof(uint8), header.key_size, file.get(), |
| 553 hash); | |
| 496 if (len < header.key_size) { | 554 if (len < header.key_size) { |
| 497 // Invalid public key | 555 // Invalid public key |
| 498 ReportFailure( | 556 ReportFailure( |
| 499 CRX_PUBLIC_KEY_INVALID, | 557 CRX_PUBLIC_KEY_INVALID, |
| 500 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE, | 558 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE, |
| 501 ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID"))); | 559 ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID"))); |
| 502 return false; | 560 return false; |
| 503 } | 561 } |
| 504 | 562 |
| 505 std::vector<uint8> signature; | 563 std::vector<uint8> signature; |
| 506 signature.resize(header.signature_size); | 564 signature.resize(header.signature_size); |
| 507 len = fread(&signature.front(), sizeof(uint8), header.signature_size, | 565 len = ReadAndHash(&signature.front(), sizeof(uint8), header.signature_size, |
| 508 file.get()); | 566 file.get(), hash); |
| 509 if (len < header.signature_size) { | 567 if (len < header.signature_size) { |
| 510 // Invalid signature | 568 // Invalid signature |
| 511 ReportFailure( | 569 ReportFailure( |
| 512 CRX_SIGNATURE_INVALID, | 570 CRX_SIGNATURE_INVALID, |
| 513 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE, | 571 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE, |
| 514 ASCIIToUTF16("CRX_SIGNATURE_INVALID"))); | 572 ASCIIToUTF16("CRX_SIGNATURE_INVALID"))); |
| 515 return false; | 573 return false; |
| 516 } | 574 } |
| 517 | 575 |
| 518 crypto::SignatureVerifier verifier; | 576 crypto::SignatureVerifier verifier; |
| 519 if (!verifier.VerifyInit( | 577 if (!verifier.VerifyInit( |
| 520 crx_file::kSignatureAlgorithm, sizeof(crx_file::kSignatureAlgorithm), | 578 crx_file::kSignatureAlgorithm, sizeof(crx_file::kSignatureAlgorithm), |
| 521 &signature.front(), signature.size(), &key.front(), key.size())) { | 579 &signature.front(), signature.size(), &key.front(), key.size())) { |
| 522 // Signature verification initialization failed. This is most likely | 580 // Signature verification initialization failed. This is most likely |
| 523 // caused by a public key in the wrong format (should encode algorithm). | 581 // caused by a public key in the wrong format (should encode algorithm). |
| 524 ReportFailure( | 582 ReportFailure( |
| 525 CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED, | 583 CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED, |
| 526 l10n_util::GetStringFUTF16( | 584 l10n_util::GetStringFUTF16( |
| 527 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 585 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
| 528 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED"))); | 586 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED"))); |
| 529 return false; | 587 return false; |
| 530 } | 588 } |
| 531 | 589 |
| 532 unsigned char buf[1 << 12]; | 590 unsigned char buf[1 << 12]; |
| 533 while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0) | 591 while ((len = ReadAndHash(buf, 1, sizeof(buf), file.get(), hash)) > 0) |
| 534 verifier.VerifyUpdate(buf, len); | 592 verifier.VerifyUpdate(buf, len); |
| 535 | 593 |
| 536 if (!verifier.VerifyFinal()) { | 594 if (!verifier.VerifyFinal()) { |
| 537 // Signature verification failed | 595 // Signature verification failed |
| 538 ReportFailure(CRX_SIGNATURE_VERIFICATION_FAILED, | 596 ReportFailure(CRX_SIGNATURE_VERIFICATION_FAILED, |
| 539 l10n_util::GetStringFUTF16( | 597 l10n_util::GetStringFUTF16( |
| 540 IDS_EXTENSION_PACKAGE_ERROR_CODE, | 598 IDS_EXTENSION_PACKAGE_ERROR_CODE, |
| 541 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED"))); | 599 ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED"))); |
| 542 return false; | 600 return false; |
| 543 } | 601 } |
| 544 | 602 |
| 603 if (!FinalizeHash(hash)) { | |
| 604 return false; | |
| 605 } | |
| 606 | |
| 545 std::string public_key = | 607 std::string public_key = |
| 546 std::string(reinterpret_cast<char*>(&key.front()), key.size()); | 608 std::string(reinterpret_cast<char*>(&key.front()), key.size()); |
| 547 base::Base64Encode(public_key, &public_key_); | 609 base::Base64Encode(public_key, &public_key_); |
| 548 | 610 |
| 549 extension_id_ = crx_file::id_util::GenerateId(public_key); | 611 extension_id_ = crx_file::id_util::GenerateId(public_key); |
| 550 | 612 |
| 551 return true; | 613 return true; |
| 552 } | 614 } |
| 553 | 615 |
| 554 void SandboxedUnpacker::ReportFailure(FailureReason reason, | 616 void SandboxedUnpacker::ReportFailure(FailureReason reason, |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 783 | 845 |
| 784 void SandboxedUnpacker::Cleanup() { | 846 void SandboxedUnpacker::Cleanup() { |
| 785 DCHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); | 847 DCHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); |
| 786 if (!temp_dir_.Delete()) { | 848 if (!temp_dir_.Delete()) { |
| 787 LOG(WARNING) << "Can not delete temp directory at " | 849 LOG(WARNING) << "Can not delete temp directory at " |
| 788 << temp_dir_.path().value(); | 850 << temp_dir_.path().value(); |
| 789 } | 851 } |
| 790 } | 852 } |
| 791 | 853 |
| 792 } // namespace extensions | 854 } // namespace extensions |
| OLD | NEW |