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