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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <set> | 10 #include <set> |
| 11 #include <tuple> | 11 #include <tuple> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 15 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 16 #include "base/json/json_string_value_serializer.h" | 16 #include "base/json/json_string_value_serializer.h" |
| 17 #include "base/message_loop/message_loop.h" | |
| 18 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
| 19 #include "base/numerics/safe_conversions.h" | |
| 20 #include "base/path_service.h" | 18 #include "base/path_service.h" |
| 21 #include "base/sequenced_task_runner.h" | 19 #include "base/sequenced_task_runner.h" |
| 22 #include "base/strings/string_number_conversions.h" | |
| 23 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 24 #include "base/threading/sequenced_worker_pool.h" | |
| 25 #include "build/build_config.h" | 21 #include "build/build_config.h" |
| 26 #include "components/crx_file/crx_file.h" | 22 #include "components/crx_file/crx_file.h" |
| 27 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 28 #include "content/public/browser/utility_process_host.h" | |
| 29 #include "content/public/common/common_param_traits.h" | |
| 30 #include "extensions/common/constants.h" | 24 #include "extensions/common/constants.h" |
| 31 #include "extensions/common/extension.h" | 25 #include "extensions/common/extension.h" |
| 32 #include "extensions/common/extension_l10n_util.h" | 26 #include "extensions/common/extension_l10n_util.h" |
| 33 #include "extensions/common/extension_utility_messages.h" | 27 #include "extensions/common/extension_utility_messages.h" |
| 28 #include "extensions/common/extension_utility_types.h" | |
| 34 #include "extensions/common/extensions_client.h" | 29 #include "extensions/common/extensions_client.h" |
| 35 #include "extensions/common/file_util.h" | 30 #include "extensions/common/file_util.h" |
| 36 #include "extensions/common/manifest_constants.h" | 31 #include "extensions/common/manifest_constants.h" |
| 37 #include "extensions/common/manifest_handlers/icons_handler.h" | 32 #include "extensions/common/manifest_handlers/icons_handler.h" |
| 38 #include "extensions/common/switches.h" | 33 #include "extensions/common/switches.h" |
| 39 #include "grit/extensions_strings.h" | 34 #include "grit/extensions_strings.h" |
| 40 #include "third_party/skia/include/core/SkBitmap.h" | 35 #include "third_party/skia/include/core/SkBitmap.h" |
| 41 #include "ui/base/l10n/l10n_util.h" | 36 #include "ui/base/l10n/l10n_util.h" |
| 42 #include "ui/gfx/codec/png_codec.h" | 37 #include "ui/gfx/codec/png_codec.h" |
| 43 | 38 |
| 44 using base::ASCIIToUTF16; | 39 using base::ASCIIToUTF16; |
| 45 using content::BrowserThread; | 40 using content::BrowserThread; |
| 46 using content::UtilityProcessHost; | |
| 47 using crx_file::CrxFile; | 41 using crx_file::CrxFile; |
| 48 | 42 |
| 49 // The following macro makes histograms that record the length of paths | 43 // The following macro makes histograms that record the length of paths |
| 50 // in this file much easier to read. | 44 // in this file much easier to read. |
| 51 // Windows has a short max path length. If the path length to a | 45 // Windows has a short max path length. If the path length to a |
| 52 // file being unpacked from a CRX exceeds the max length, we might | 46 // file being unpacked from a CRX exceeds the max length, we might |
| 53 // fail to install. To see if this is happening, see how long the | 47 // fail to install. To see if this is happening, see how long the |
| 54 // path to the temp unpack directory is. See crbug.com/69693 . | 48 // path to the temp unpack directory is. See crbug.com/69693 . |
| 55 #define PATH_LENGTH_HISTOGRAM(name, path) \ | 49 #define PATH_LENGTH_HISTOGRAM(name, path) \ |
| 56 UMA_HISTOGRAM_CUSTOM_COUNTS(name, path.value().length(), 1, 500, 100) | 50 UMA_HISTOGRAM_CUSTOM_COUNTS(name, path.value().length(), 1, 500, 100) |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 } | 211 } |
| 218 | 212 |
| 219 SandboxedUnpacker::SandboxedUnpacker( | 213 SandboxedUnpacker::SandboxedUnpacker( |
| 220 Manifest::Location location, | 214 Manifest::Location location, |
| 221 int creation_flags, | 215 int creation_flags, |
| 222 const base::FilePath& extensions_dir, | 216 const base::FilePath& extensions_dir, |
| 223 const scoped_refptr<base::SequencedTaskRunner>& unpacker_io_task_runner, | 217 const scoped_refptr<base::SequencedTaskRunner>& unpacker_io_task_runner, |
| 224 SandboxedUnpackerClient* client) | 218 SandboxedUnpackerClient* client) |
| 225 : client_(client), | 219 : client_(client), |
| 226 extensions_dir_(extensions_dir), | 220 extensions_dir_(extensions_dir), |
| 227 got_response_(false), | |
| 228 location_(location), | 221 location_(location), |
| 229 creation_flags_(creation_flags), | 222 creation_flags_(creation_flags), |
| 230 unpacker_io_task_runner_(unpacker_io_task_runner), | 223 unpacker_io_task_runner_(unpacker_io_task_runner) {} |
| 231 utility_wrapper_(new UtilityHostWrapper) {} | |
| 232 | 224 |
| 233 bool SandboxedUnpacker::CreateTempDirectory() { | 225 bool SandboxedUnpacker::CreateTempDirectory() { |
| 234 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); | 226 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); |
| 235 | 227 |
| 236 base::FilePath temp_dir; | 228 base::FilePath temp_dir; |
| 237 if (!FindWritableTempLocation(extensions_dir_, &temp_dir)) { | 229 if (!FindWritableTempLocation(extensions_dir_, &temp_dir)) { |
| 238 ReportFailure(COULD_NOT_GET_TEMP_DIRECTORY, | 230 ReportFailure(COULD_NOT_GET_TEMP_DIRECTORY, |
| 239 l10n_util::GetStringFUTF16( | 231 l10n_util::GetStringFUTF16( |
| 240 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 232 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
| 241 ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY"))); | 233 ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY"))); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 306 LOG(ERROR) << "Could not get the normalized path of " | 298 LOG(ERROR) << "Could not get the normalized path of " |
| 307 << temp_crx_path.value(); | 299 << temp_crx_path.value(); |
| 308 ReportFailure(COULD_NOT_GET_SANDBOX_FRIENDLY_PATH, | 300 ReportFailure(COULD_NOT_GET_SANDBOX_FRIENDLY_PATH, |
| 309 l10n_util::GetStringUTF16(IDS_EXTENSION_UNPACK_FAILED)); | 301 l10n_util::GetStringUTF16(IDS_EXTENSION_UNPACK_FAILED)); |
| 310 return; | 302 return; |
| 311 } | 303 } |
| 312 PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackLinkFreeCrxPathLength", | 304 PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackLinkFreeCrxPathLength", |
| 313 link_free_crx_path); | 305 link_free_crx_path); |
| 314 | 306 |
| 315 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 307 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 316 base::Bind(&SandboxedUnpacker::StartUnzipOnIOThread, | 308 base::Bind(&SandboxedUnpacker::UnzipOnIOThread, this, |
| 317 this, link_free_crx_path)); | 309 link_free_crx_path)); |
| 318 } | 310 } |
| 319 | 311 |
| 320 void SandboxedUnpacker::StartWithDirectory(const std::string& extension_id, | 312 void SandboxedUnpacker::StartWithDirectory(const std::string& extension_id, |
| 321 const std::string& public_key, | 313 const std::string& public_key, |
| 322 const base::FilePath& directory) { | 314 const base::FilePath& directory) { |
| 323 extension_id_ = extension_id; | 315 extension_id_ = extension_id; |
| 324 public_key_ = public_key; | 316 public_key_ = public_key; |
| 325 if (!CreateTempDirectory()) | 317 if (!CreateTempDirectory()) |
| 326 return; // ReportFailure() already called. | 318 return; // ReportFailure() already called. |
| 327 | 319 |
| 328 extension_root_ = temp_dir_.GetPath().AppendASCII(kTempExtensionName); | 320 extension_root_ = temp_dir_.GetPath().AppendASCII(kTempExtensionName); |
| 329 | 321 |
| 330 if (!base::Move(directory, extension_root_)) { | 322 if (!base::Move(directory, extension_root_)) { |
| 331 LOG(ERROR) << "Could not move " << directory.value() << " to " | 323 LOG(ERROR) << "Could not move " << directory.value() << " to " |
| 332 << extension_root_.value(); | 324 << extension_root_.value(); |
| 333 ReportFailure( | 325 ReportFailure( |
| 334 DIRECTORY_MOVE_FAILED, | 326 DIRECTORY_MOVE_FAILED, |
| 335 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 327 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
| 336 ASCIIToUTF16("DIRECTORY_MOVE_FAILED"))); | 328 ASCIIToUTF16("DIRECTORY_MOVE_FAILED"))); |
| 337 return; | 329 return; |
| 338 } | 330 } |
| 339 | 331 |
| 340 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 332 BrowserThread::PostTask( |
| 341 base::Bind(&SandboxedUnpacker::StartUnpackOnIOThread, | 333 BrowserThread::IO, FROM_HERE, |
| 342 this, extension_root_)); | 334 base::Bind(&SandboxedUnpacker::UnpackOnIOThread, this, extension_root_)); |
| 343 } | 335 } |
| 344 | 336 |
| 345 SandboxedUnpacker::~SandboxedUnpacker() { | 337 SandboxedUnpacker::~SandboxedUnpacker() { |
| 346 // To avoid blocking shutdown, don't delete temporary directory here if it | 338 // To avoid blocking shutdown, don't delete temporary directory here if it |
| 347 // hasn't been cleaned up or passed on to another owner yet. | 339 // hasn't been cleaned up or passed on to another owner yet. |
| 348 temp_dir_.Take(); | 340 temp_dir_.Take(); |
| 349 } | 341 } |
| 350 | 342 |
| 351 bool SandboxedUnpacker::OnMessageReceived(const IPC::Message& message) { | 343 void SandboxedUnpacker::StartUtilityProcess(const base::FilePath& dir) { |
| 352 bool handled = true; | 344 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 353 IPC_BEGIN_MESSAGE_MAP(SandboxedUnpacker, message) | 345 DCHECK(!dir.empty()); |
| 354 IPC_MESSAGE_HANDLER(ExtensionUtilityHostMsg_UnzipToDir_Succeeded, | 346 |
| 355 OnUnzipToDirSucceeded) | 347 if (utility_process_mojo_client_) |
| 356 IPC_MESSAGE_HANDLER(ExtensionUtilityHostMsg_UnzipToDir_Failed, | 348 return; |
| 357 OnUnzipToDirFailed) | 349 |
| 358 IPC_MESSAGE_HANDLER(ExtensionUtilityHostMsg_UnpackExtension_Succeeded, | 350 const base::string16 utility_process_name = |
| 359 OnUnpackExtensionSucceeded) | 351 l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_EXTENSION_UNPACKER_NAME); |
| 360 IPC_MESSAGE_HANDLER(ExtensionUtilityHostMsg_UnpackExtension_Failed, | 352 |
| 361 OnUnpackExtensionFailed) | 353 utility_process_mojo_client_.reset( |
|
Sam McNally
2017/02/14 05:41:52
utility_process_mojo_client_ = base::MakeUnique<co
Noel Gordon
2017/02/14 12:35:37
Done.
| |
| 362 IPC_MESSAGE_UNHANDLED(handled = false) | 354 new content::UtilityProcessMojoClient< |
| 363 IPC_END_MESSAGE_MAP() | 355 extensions::mojom::ExtensionUnpacker>(utility_process_name)); |
| 364 return handled; | 356 utility_process_mojo_client_->set_error_callback( |
| 357 base::Bind(&SandboxedUnpacker::UtilityProcessCrashed, this)); | |
| 358 | |
| 359 utility_process_mojo_client_->set_exposed_directory(dir); | |
| 360 | |
| 361 utility_process_mojo_client_->Start(); | |
| 365 } | 362 } |
| 366 | 363 |
| 367 void SandboxedUnpacker::OnProcessCrashed(int exit_code) { | 364 void SandboxedUnpacker::UtilityProcessCrashed() { |
| 368 // Don't report crashes if they happen after we got a response. | 365 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 369 if (got_response_) | |
| 370 return; | |
| 371 | 366 |
| 372 // Utility process crashed while trying to install. | 367 utility_process_mojo_client_.reset(); |
| 368 | |
| 373 ReportFailure( | 369 ReportFailure( |
| 374 UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL, | 370 UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL, |
| 375 l10n_util::GetStringFUTF16( | 371 l10n_util::GetStringFUTF16( |
| 376 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 372 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
| 377 ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) + | 373 ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) + |
| 378 ASCIIToUTF16(". ") + | 374 ASCIIToUTF16(". ") + |
| 379 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_PROCESS_CRASHED)); | 375 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_PROCESS_CRASHED)); |
| 380 } | 376 } |
| 381 | 377 |
| 382 void SandboxedUnpacker::StartUnzipOnIOThread(const base::FilePath& crx_path) { | 378 void SandboxedUnpacker::UnzipOnIOThread(const base::FilePath& crx_path) { |
| 383 if (!utility_wrapper_->StartIfNeeded(temp_dir_.GetPath(), this, | 379 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 384 unpacker_io_task_runner_)) { | 380 |
| 385 ReportFailure( | 381 StartUtilityProcess(temp_dir_.GetPath()); |
| 386 COULD_NOT_START_UTILITY_PROCESS, | 382 |
| 387 l10n_util::GetStringFUTF16( | |
| 388 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | |
| 389 FailureReasonToString16(COULD_NOT_START_UTILITY_PROCESS))); | |
| 390 return; | |
| 391 } | |
| 392 DCHECK(crx_path.DirName() == temp_dir_.GetPath()); | 383 DCHECK(crx_path.DirName() == temp_dir_.GetPath()); |
| 393 base::FilePath unzipped_dir = | 384 base::FilePath unzipped_dir = |
| 394 crx_path.DirName().AppendASCII(kTempExtensionName); | 385 crx_path.DirName().AppendASCII(kTempExtensionName); |
| 395 utility_wrapper_->host()->Send( | 386 |
| 396 new ExtensionUtilityMsg_UnzipToDir(crx_path, unzipped_dir)); | 387 utility_process_mojo_client_->service()->Unzip( |
| 388 crx_path, unzipped_dir, | |
| 389 base::Bind(&SandboxedUnpacker::UnzipDone, this, unzipped_dir)); | |
| 397 } | 390 } |
| 398 | 391 |
| 399 void SandboxedUnpacker::StartUnpackOnIOThread( | 392 void SandboxedUnpacker::UnzipDone(const base::FilePath& directory, |
| 400 const base::FilePath& directory_path) { | 393 bool success) { |
| 401 if (!utility_wrapper_->StartIfNeeded(temp_dir_.GetPath(), this, | 394 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 402 unpacker_io_task_runner_)) { | 395 |
| 403 ReportFailure( | 396 if (!success) { |
| 404 COULD_NOT_START_UTILITY_PROCESS, | 397 utility_process_mojo_client_.reset(); |
| 405 l10n_util::GetStringFUTF16( | 398 ReportFailure(UNZIP_FAILED, |
| 406 IDS_EXTENSION_PACKAGE_INSTALL_ERROR, | 399 l10n_util::GetStringUTF16(IDS_EXTENSION_PACKAGE_UNZIP_ERROR)); |
| 407 FailureReasonToString16(COULD_NOT_START_UTILITY_PROCESS))); | |
| 408 return; | 400 return; |
| 409 } | 401 } |
| 410 DCHECK(directory_path.DirName() == temp_dir_.GetPath()); | 402 |
| 411 utility_wrapper_->host()->Send(new ExtensionUtilityMsg_UnpackExtension( | 403 BrowserThread::PostTask( |
| 412 directory_path, extension_id_, location_, creation_flags_)); | 404 BrowserThread::IO, FROM_HERE, |
| 405 base::Bind(&SandboxedUnpacker::UnpackOnIOThread, this, directory)); | |
| 413 } | 406 } |
| 414 | 407 |
| 415 void SandboxedUnpacker::OnUnzipToDirSucceeded(const base::FilePath& directory) { | 408 void SandboxedUnpacker::UnpackOnIOThread(const base::FilePath& directory) { |
| 416 BrowserThread::PostTask( | 409 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 417 BrowserThread::IO, FROM_HERE, | 410 |
| 418 base::Bind(&SandboxedUnpacker::StartUnpackOnIOThread, this, directory)); | 411 StartUtilityProcess(temp_dir_.GetPath()); |
| 412 | |
| 413 DCHECK(directory.DirName() == temp_dir_.GetPath()); | |
| 414 | |
| 415 utility_process_mojo_client_->service()->Unpack( | |
| 416 directory, extension_id_, location_, creation_flags_, | |
| 417 base::Bind(&SandboxedUnpacker::UnpackDone, this)); | |
| 419 } | 418 } |
| 420 | 419 |
| 421 void SandboxedUnpacker::OnUnzipToDirFailed(const std::string& error) { | 420 void SandboxedUnpacker::UnpackDone( |
| 422 got_response_ = true; | 421 const base::string16& error, |
| 423 utility_wrapper_ = nullptr; | 422 std::unique_ptr<base::DictionaryValue> manifest) { |
| 424 ReportFailure(UNZIP_FAILED, | 423 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 425 l10n_util::GetStringUTF16(IDS_EXTENSION_PACKAGE_UNZIP_ERROR)); | 424 |
| 425 utility_process_mojo_client_.reset(); | |
| 426 | |
| 427 if (!error.empty()) { | |
| 428 unpacker_io_task_runner_->PostTask( | |
| 429 FROM_HERE, | |
| 430 base::Bind(&SandboxedUnpacker::UnpackExtensionFailed, this, error)); | |
| 431 return; | |
| 432 } | |
| 433 | |
| 434 unpacker_io_task_runner_->PostTask( | |
| 435 FROM_HERE, base::Bind(&SandboxedUnpacker::UnpackExtensionSucceeded, this, | |
| 436 base::Passed(&manifest))); | |
| 426 } | 437 } |
| 427 | 438 |
| 428 void SandboxedUnpacker::OnUnpackExtensionSucceeded( | 439 void SandboxedUnpacker::UnpackExtensionSucceeded( |
| 429 const base::DictionaryValue& manifest) { | 440 std::unique_ptr<base::DictionaryValue> manifest) { |
| 430 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); | 441 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); |
| 431 got_response_ = true; | |
| 432 utility_wrapper_ = nullptr; | |
| 433 | 442 |
| 434 std::unique_ptr<base::DictionaryValue> final_manifest( | 443 std::unique_ptr<base::DictionaryValue> final_manifest( |
| 435 RewriteManifestFile(manifest)); | 444 RewriteManifestFile(*manifest.get())); |
| 436 if (!final_manifest) | 445 if (!final_manifest) |
| 437 return; | 446 return; |
| 438 | 447 |
| 439 // Create an extension object that refers to the temporary location the | 448 // Create an extension object that refers to the temporary location the |
| 440 // extension was unpacked to. We use this until the extension is finally | 449 // extension was unpacked to. We use this until the extension is finally |
| 441 // installed. For example, the install UI shows images from inside the | 450 // installed. For example, the install UI shows images from inside the |
| 442 // extension. | 451 // extension. |
| 443 | 452 |
| 444 // Localize manifest now, so confirm UI gets correct extension name. | 453 // Localize manifest now, so confirm UI gets correct extension name. |
| 445 | 454 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 465 return; | 474 return; |
| 466 } | 475 } |
| 467 | 476 |
| 468 SkBitmap install_icon; | 477 SkBitmap install_icon; |
| 469 if (!RewriteImageFiles(&install_icon)) | 478 if (!RewriteImageFiles(&install_icon)) |
| 470 return; | 479 return; |
| 471 | 480 |
| 472 if (!RewriteCatalogFiles()) | 481 if (!RewriteCatalogFiles()) |
| 473 return; | 482 return; |
| 474 | 483 |
| 475 ReportSuccess(manifest, install_icon); | 484 ReportSuccess(std::move(manifest), install_icon); |
| 476 } | 485 } |
| 477 | 486 |
| 478 void SandboxedUnpacker::OnUnpackExtensionFailed(const base::string16& error) { | 487 void SandboxedUnpacker::UnpackExtensionFailed(const base::string16& error) { |
| 479 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); | 488 CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); |
| 480 got_response_ = true; | 489 |
| 481 utility_wrapper_ = nullptr; | |
| 482 ReportFailure( | 490 ReportFailure( |
| 483 UNPACKER_CLIENT_FAILED, | 491 UNPACKER_CLIENT_FAILED, |
| 484 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, error)); | 492 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, error)); |
| 485 } | 493 } |
| 486 | 494 |
| 487 base::string16 SandboxedUnpacker::FailureReasonToString16( | 495 base::string16 SandboxedUnpacker::FailureReasonToString16( |
| 488 FailureReason reason) { | 496 FailureReason reason) { |
| 489 switch (reason) { | 497 switch (reason) { |
| 490 case COULD_NOT_GET_TEMP_DIRECTORY: | 498 case COULD_NOT_GET_TEMP_DIRECTORY: |
| 491 return ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY"); | 499 return ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY"); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 560 case ERROR_SAVING_CATALOG: | 568 case ERROR_SAVING_CATALOG: |
| 561 return ASCIIToUTF16("ERROR_SAVING_CATALOG"); | 569 return ASCIIToUTF16("ERROR_SAVING_CATALOG"); |
| 562 | 570 |
| 563 case CRX_HASH_VERIFICATION_FAILED: | 571 case CRX_HASH_VERIFICATION_FAILED: |
| 564 return ASCIIToUTF16("CRX_HASH_VERIFICATION_FAILED"); | 572 return ASCIIToUTF16("CRX_HASH_VERIFICATION_FAILED"); |
| 565 | 573 |
| 566 case UNZIP_FAILED: | 574 case UNZIP_FAILED: |
| 567 return ASCIIToUTF16("UNZIP_FAILED"); | 575 return ASCIIToUTF16("UNZIP_FAILED"); |
| 568 case DIRECTORY_MOVE_FAILED: | 576 case DIRECTORY_MOVE_FAILED: |
| 569 return ASCIIToUTF16("DIRECTORY_MOVE_FAILED"); | 577 return ASCIIToUTF16("DIRECTORY_MOVE_FAILED"); |
| 570 case COULD_NOT_START_UTILITY_PROCESS: | |
| 571 return ASCIIToUTF16("COULD_NOT_START_UTILITY_PROCESS"); | |
| 572 | 578 |
| 573 case NUM_FAILURE_REASONS: | 579 case NUM_FAILURE_REASONS: |
| 574 NOTREACHED(); | 580 NOTREACHED(); |
| 575 return base::string16(); | 581 return base::string16(); |
| 576 } | 582 } |
| 583 | |
| 577 NOTREACHED(); | 584 NOTREACHED(); |
| 578 return base::string16(); | 585 return base::string16(); |
| 579 } | 586 } |
| 580 | 587 |
| 581 void SandboxedUnpacker::FailWithPackageError(FailureReason reason) { | 588 void SandboxedUnpacker::FailWithPackageError(FailureReason reason) { |
| 582 ReportFailure(reason, | 589 ReportFailure(reason, |
| 583 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE, | 590 l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_CODE, |
| 584 FailureReasonToString16(reason))); | 591 FailureReasonToString16(reason))); |
| 585 } | 592 } |
| 586 | 593 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 636 CHECK(!expected_hash.empty()); | 643 CHECK(!expected_hash.empty()); |
| 637 UMA_HISTOGRAM_BOOLEAN("Extensions.SandboxUnpackHashCheck", false); | 644 UMA_HISTOGRAM_BOOLEAN("Extensions.SandboxUnpackHashCheck", false); |
| 638 FailWithPackageError(CRX_HASH_VERIFICATION_FAILED); | 645 FailWithPackageError(CRX_HASH_VERIFICATION_FAILED); |
| 639 break; | 646 break; |
| 640 } | 647 } |
| 641 return false; | 648 return false; |
| 642 } | 649 } |
| 643 | 650 |
| 644 void SandboxedUnpacker::ReportFailure(FailureReason reason, | 651 void SandboxedUnpacker::ReportFailure(FailureReason reason, |
| 645 const base::string16& error) { | 652 const base::string16& error) { |
| 646 utility_wrapper_ = nullptr; | |
| 647 UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", reason, | 653 UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", reason, |
| 648 NUM_FAILURE_REASONS); | 654 NUM_FAILURE_REASONS); |
| 649 if (!crx_unpack_start_time_.is_null()) | 655 if (!crx_unpack_start_time_.is_null()) |
| 650 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackFailureTime", | 656 UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackFailureTime", |
| 651 base::TimeTicks::Now() - crx_unpack_start_time_); | 657 base::TimeTicks::Now() - crx_unpack_start_time_); |
| 652 Cleanup(); | 658 Cleanup(); |
| 653 | 659 |
| 654 CrxInstallError error_info(reason == CRX_HASH_VERIFICATION_FAILED | 660 CrxInstallError error_info(reason == CRX_HASH_VERIFICATION_FAILED |
| 655 ? CrxInstallError::ERROR_HASH_MISMATCH | 661 ? CrxInstallError::ERROR_HASH_MISMATCH |
| 656 : CrxInstallError::ERROR_OTHER, | 662 : CrxInstallError::ERROR_OTHER, |
| 657 error); | 663 error); |
| 658 | 664 |
| 659 client_->OnUnpackFailure(error_info); | 665 client_->OnUnpackFailure(error_info); |
| 660 } | 666 } |
| 661 | 667 |
| 662 void SandboxedUnpacker::ReportSuccess( | 668 void SandboxedUnpacker::ReportSuccess( |
| 663 const base::DictionaryValue& original_manifest, | 669 std::unique_ptr<base::DictionaryValue> original_manifest, |
| 664 const SkBitmap& install_icon) { | 670 const SkBitmap& install_icon) { |
| 665 utility_wrapper_ = nullptr; | |
| 666 UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccess", 1); | 671 UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccess", 1); |
| 667 | 672 |
| 668 if (!crx_unpack_start_time_.is_null()) | 673 if (!crx_unpack_start_time_.is_null()) |
| 669 RecordSuccessfulUnpackTimeHistograms( | 674 RecordSuccessfulUnpackTimeHistograms( |
| 670 crx_path_for_histograms_, | 675 crx_path_for_histograms_, |
| 671 base::TimeTicks::Now() - crx_unpack_start_time_); | 676 base::TimeTicks::Now() - crx_unpack_start_time_); |
| 672 DCHECK(!temp_dir_.GetPath().empty()); | 677 DCHECK(!temp_dir_.GetPath().empty()); |
| 673 | 678 |
| 674 // Client takes ownership of temporary directory and extension. | 679 // Client takes ownership of temporary directory and extension. |
| 675 client_->OnUnpackSuccess(temp_dir_.Take(), extension_root_, | 680 client_->OnUnpackSuccess(temp_dir_.Take(), extension_root_, |
| 676 &original_manifest, extension_.get(), install_icon); | 681 original_manifest.get(), extension_.get(), |
| 682 install_icon); | |
| 677 extension_ = NULL; | 683 extension_ = NULL; |
| 678 } | 684 } |
| 679 | 685 |
| 680 base::DictionaryValue* SandboxedUnpacker::RewriteManifestFile( | 686 base::DictionaryValue* SandboxedUnpacker::RewriteManifestFile( |
| 681 const base::DictionaryValue& manifest) { | 687 const base::DictionaryValue& manifest) { |
| 682 // Add the public key extracted earlier to the parsed manifest and overwrite | 688 // Add the public key extracted earlier to the parsed manifest and overwrite |
| 683 // the original manifest. We do this to ensure the manifest doesn't contain an | 689 // the original manifest. We do this to ensure the manifest doesn't contain an |
| 684 // exploitable bug that could be used to compromise the browser. | 690 // exploitable bug that could be used to compromise the browser. |
| 685 DCHECK(!public_key_.empty()); | 691 DCHECK(!public_key_.empty()); |
| 686 std::unique_ptr<base::DictionaryValue> final_manifest(manifest.DeepCopy()); | 692 std::unique_ptr<base::DictionaryValue> final_manifest(manifest.DeepCopy()); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 886 } | 892 } |
| 887 | 893 |
| 888 void SandboxedUnpacker::Cleanup() { | 894 void SandboxedUnpacker::Cleanup() { |
| 889 DCHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); | 895 DCHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); |
| 890 if (!temp_dir_.Delete()) { | 896 if (!temp_dir_.Delete()) { |
| 891 LOG(WARNING) << "Can not delete temp directory at " | 897 LOG(WARNING) << "Can not delete temp directory at " |
| 892 << temp_dir_.GetPath().value(); | 898 << temp_dir_.GetPath().value(); |
| 893 } | 899 } |
| 894 } | 900 } |
| 895 | 901 |
| 896 SandboxedUnpacker::UtilityHostWrapper::UtilityHostWrapper() {} | |
| 897 | |
| 898 bool SandboxedUnpacker::UtilityHostWrapper::StartIfNeeded( | |
| 899 const base::FilePath& exposed_dir, | |
| 900 const scoped_refptr<UtilityProcessHostClient>& client, | |
| 901 const scoped_refptr<base::SequencedTaskRunner>& client_task_runner) { | |
| 902 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 903 if (!utility_host_) { | |
| 904 utility_host_ = | |
| 905 UtilityProcessHost::Create(client, client_task_runner)->AsWeakPtr(); | |
| 906 utility_host_->SetName( | |
| 907 l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_EXTENSION_UNPACKER_NAME)); | |
| 908 | |
| 909 // Grant the subprocess access to our temp dir so it can write out files. | |
| 910 DCHECK(!exposed_dir.empty()); | |
| 911 utility_host_->SetExposedDir(exposed_dir); | |
| 912 if (!utility_host_->StartBatchMode()) { | |
| 913 utility_host_.reset(); | |
| 914 return false; | |
| 915 } | |
| 916 } | |
| 917 return true; | |
| 918 } | |
| 919 | |
| 920 content::UtilityProcessHost* SandboxedUnpacker::UtilityHostWrapper::host() | |
| 921 const { | |
| 922 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 923 return utility_host_.get(); | |
| 924 } | |
| 925 | |
| 926 SandboxedUnpacker::UtilityHostWrapper::~UtilityHostWrapper() { | |
| 927 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 928 if (utility_host_) { | |
| 929 utility_host_->EndBatchMode(); | |
| 930 utility_host_.reset(); | |
| 931 } | |
| 932 } | |
| 933 | |
| 934 } // namespace extensions | 902 } // namespace extensions |
| OLD | NEW |