15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/sandboxed_unpacker.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_util_proxy.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/files/scoped_file.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_string_value_serializer.h" 16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/numerics/safe_conversions.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/sequenced_task_runner.h" 2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/threading/sequenced_worker_pool.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_utility_messages.h" 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/chrome_utility_extensions_messages.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_file_util.h" 2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/crx_file/constants.h" 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/crx_file/crx_file.h" 3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/utility_process_host.h" 357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/common/common_param_traits.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/signature_verifier.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h" 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension_l10n_util.h" 40a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/common/file_util.h" 413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest_constants.h" 42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::UtilityProcessHost; 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using crx_file::CrxFile; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following macro makes histograms that record the length of paths 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in this file much easier to read. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows has a short max path length. If the path length to a 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// file being unpacked from a CRX exceeds the max length, we might 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fail to install. To see if this is happening, see how long the 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// path to the temp unpack directory is. See crbug.com/69693 . 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PATH_LENGTH_HISTOGRAM(name, path) \ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS(name, path.value().length(), 0, 500, 100) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Record a rate (kB per second) at which extensions are unpacked. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Range from 1kB/s to 100mB/s. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNPACK_RATE_HISTOGRAM(name, rate) \ 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS(name, rate, 1, 100000, 100); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace extensions { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecordSuccessfulUnpackTimeHistograms( 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& crx_path, const base::TimeDelta unpack_time) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int64 kBytesPerKb = 1024; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int64 kBytesPerMb = 1024 * 1024; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackSuccessTime", unpack_time); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To get a sense of how CRX size impacts unpack time, record unpack 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time for several increments of CRX size. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 crx_file_size; 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::GetFileSize(crx_path, &crx_file_size)) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccessCantGetCrxSize", 1); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cast is safe as long as the number of bytes in the CRX is less than 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2^31 * 2^10. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int crx_file_size_kb = static_cast<int>(crx_file_size / kBytesPerKb); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS( 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackSuccessCrxSize", crx_file_size_kb); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have time in seconds and file size in bytes. We want the rate bytes are 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unpacked in kB/s. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double file_size_kb = 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<double>(crx_file_size) / static_cast<double>(kBytesPerKb); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int unpack_rate_kb_per_s = 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(file_size_kb / unpack_time.InSecondsF()); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRate", unpack_rate_kb_per_s); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crx_file_size < 50.0 * kBytesPerKb) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRateUnder50kB", unpack_rate_kb_per_s); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (crx_file_size < 1 * kBytesPerMb) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRate50kBTo1mB", unpack_rate_kb_per_s); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (crx_file_size < 2 * kBytesPerMb) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRate1To2mB", unpack_rate_kb_per_s); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (crx_file_size < 5 * kBytesPerMb) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRate2To5mB", unpack_rate_kb_per_s); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (crx_file_size < 10 * kBytesPerMb) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRate5To10mB", unpack_rate_kb_per_s); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRateOver10mB", unpack_rate_kb_per_s); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Work horse for FindWritableTempLocation. Creates a temp file in the folder 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and uses NormalizeFilePath to check if the path is junction free. 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VerifyJunctionFreeLocation(base::FilePath* temp_dir) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (temp_dir->empty()) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath temp_file; 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateTemporaryFileInDir(*temp_dir, &temp_file)) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << temp_dir->value() << " is not writable"; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NormalizeFilePath requires a non-empty file, so write some data. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If you change the exit points of this function please make sure all 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exit points delete this temp file! 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::WriteFile(temp_file, ".", 1) != 1) 140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath normalized_temp_file; 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool normalized = base::NormalizeFilePath(temp_file, &normalized_temp_file); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!normalized) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |temp_file| contains a link, the sandbox will block al file system 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operations, and the install will fail. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << temp_dir->value() << " seem to be on remote drive."; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *temp_dir = normalized_temp_file.DirName(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clean up the temp file. 1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(temp_file, false); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return normalized; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function tries to find a location for unpacking the extension archive 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that is writable and does not lie on a shared drive so that the sandboxed 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unpacking process can write there. If no such location exists we can not 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// proceed and should fail. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The result will be written to |temp_dir|. The function will write to this 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parameter even if it returns false. 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FindWritableTempLocation(const base::FilePath& extensions_dir, 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath* temp_dir) { 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// On ChromeOS, we will only attempt to unpack extension in cryptohome (profile) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// directory to provide additional security/privacy and speed up the rest of 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the extension install process. 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_CHROMEOS) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathService::Get(base::DIR_TEMP, temp_dir); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VerifyJunctionFreeLocation(temp_dir)) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch *temp_dir = file_util::GetInstallTempDir(extensions_dir); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VerifyJunctionFreeLocation(temp_dir)) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Neither paths is link free chances are good installation will fail. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Both the %TEMP% folder and the profile seem to be on " 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "remote drives or read-only. Installation can not complete!"; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Read the decoded images back from the file we saved them to. 1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// |extension_path| is the path to the extension we unpacked that wrote the 1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// data. Returns true on success. 1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool ReadImagesFromFile(const base::FilePath& extension_path, 1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DecodedImages* images) { 1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::FilePath path = 189a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch extension_path.AppendASCII(kDecodedImagesFilename); 1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string file_str; 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!base::ReadFileToString(path, &file_str)) 1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch IPC::Message pickle(file_str.data(), file_str.size()); 1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PickleIterator iter(pickle); 1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return IPC::ReadParam(&pickle, &iter, images); 1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Read the decoded message catalogs back from the file we saved them to. 2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// |extension_path| is the path to the extension we unpacked that wrote the 2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// data. Returns true on success. 2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool ReadMessageCatalogsFromFile(const base::FilePath& extension_path, 2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DictionaryValue* catalogs) { 2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::FilePath path = extension_path.AppendASCII( 205a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch kDecodedMessageCatalogsFilename); 2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string file_str; 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!base::ReadFileToString(path, &file_str)) 2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch IPC::Message pickle(file_str.data(), file_str.size()); 2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PickleIterator iter(pickle); 2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return IPC::ReadParam(&pickle, &iter, catalogs); 2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SandboxedUnpacker::SandboxedUnpacker( 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& crx_path, 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Manifest::Location location, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int creation_flags, 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& extensions_dir, 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::SequencedTaskRunner>& unpacker_io_task_runner, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SandboxedUnpackerClient* client) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : crx_path_(crx_path), 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_(client), 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions_dir_(extensions_dir), 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_response_(false), 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) location_(location), 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) creation_flags_(creation_flags), 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unpacker_io_task_runner_(unpacker_io_task_runner) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SandboxedUnpacker::CreateTempDirectory() { 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath temp_dir; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FindWritableTempLocation(extensions_dir_, &temp_dir)) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_GET_TEMP_DIRECTORY, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY"))); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!temp_dir_.CreateUniqueTempDirUnderPath(temp_dir)) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_CREATE_TEMP_DIRECTORY, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("COULD_NOT_CREATE_TEMP_DIRECTORY"))); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::Start() { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We assume that we are started on the thread that the client wants us to do 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file IO on. 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unpack_start_time_ = base::TimeTicks::Now(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackInitialCrxPathLength", 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crx_path_); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateTempDirectory()) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // ReportFailure() already called. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the path that will eventually contain the unpacked extension. 271a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch extension_root_ = temp_dir_.path().AppendASCII(kTempExtensionName); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackUnpackedCrxPathLength", 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_root_); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Extract the public key and validate the package. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ValidateSignature()) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // ValidateSignature() already reported the error. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the crx file into our working directory. 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath temp_crx_path = temp_dir_.path().Append(crx_path_.BaseName()); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackTempCrxPathLength", 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_crx_path); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::CopyFile(crx_path_, temp_crx_path)) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Failed to copy extension file to temporary directory. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY"))); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The utility process will have access to the directory passed to 2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SandboxedUnpacker. That directory should not contain a symlink or NTFS 2967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // reparse point. When the path is used, following the link/reparse point 2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // will cause file system access outside the sandbox path, and the sandbox 2987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // will deny the operation. 2997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::FilePath link_free_crx_path; 300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::NormalizeFilePath(temp_crx_path, &link_free_crx_path)) { 3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch LOG(ERROR) << "Could not get the normalized path of " 3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch << temp_crx_path.value(); 3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ReportFailure( 3047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch COULD_NOT_GET_SANDBOX_FRIENDLY_PATH, 3057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch l10n_util::GetStringUTF16(IDS_EXTENSION_UNPACK_FAILED)); 3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackLinkFreeCrxPathLength", 3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch link_free_crx_path); 3107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BrowserThread::PostTask( 3127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BrowserThread::IO, FROM_HERE, 3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Bind( 3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &SandboxedUnpacker::StartProcessOnIOThread, 3157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this, 3167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch link_free_crx_path)); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SandboxedUnpacker::~SandboxedUnpacker() { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SandboxedUnpacker::OnMessageReceived(const IPC::Message& message) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(SandboxedUnpacker, message) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackExtension_Succeeded, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnUnpackExtensionSucceeded) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackExtension_Failed, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnUnpackExtensionFailed) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_END_MESSAGE_MAP() 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handled; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::OnProcessCrashed(int exit_code) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't report crashes if they happen after we got a response. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (got_response_) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Utility process crashed while trying to install. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL, 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) + 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASCIIToUTF16(". ") + 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_PROCESS_CRASHED)); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SandboxedUnpacker::StartProcessOnIOThread( 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& temp_crx_path) { 351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UtilityProcessHost* host = 352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UtilityProcessHost::Create(this, unpacker_io_task_runner_.get()); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Grant the subprocess access to the entire subdir the extension file is 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in, so that it can unpack to that dir. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->SetExposedDir(temp_crx_path.DirName()); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->Send( 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ChromeUtilityMsg_UnpackExtension( 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_crx_path, extension_id_, location_, creation_flags_)); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::OnUnpackExtensionSucceeded( 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue& manifest) { 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_response_ = true; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> final_manifest( 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RewriteManifestFile(manifest)); 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!final_manifest) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an extension object that refers to the temporary location the 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extension was unpacked to. We use this until the extension is finally 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // installed. For example, the install UI shows images from inside the 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extension. 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Localize manifest now, so confirm UI gets correct extension name. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rdevlin.cronin): Continue removing std::string errors and replacing 379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // with base::string16 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string utf8_error; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_l10n_util::LocalizeExtension(extension_root_, 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final_manifest.get(), 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &utf8_error)) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_LOCALIZE_EXTENSION, 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(utf8_error))); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_ = Extension::Create( 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_root_, 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) location_, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *final_manifest, 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Extension::REQUIRE_KEY | creation_flags_, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &utf8_error); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!extension_.get()) { 400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ReportFailure(INVALID_MANIFEST, 401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASCIIToUTF16("Manifest is invalid: " + utf8_error)); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SkBitmap install_icon; 4067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!RewriteImageFiles(&install_icon)) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RewriteCatalogFiles()) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ReportSuccess(manifest, install_icon); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SandboxedUnpacker::OnUnpackExtensionFailed(const base::string16& error) { 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_response_ = true; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACKER_CLIENT_FAILED, 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error)); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SandboxedUnpacker::ValidateSignature() { 426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::ScopedFILE file(base::OpenFile(crx_path_, "rb")); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file.get()) { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Could not open crx file for reading. 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined (OS_WIN) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On windows, get the error code. 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 error_code = ::GetLastError(); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(skerner): Use this histogram to understand why so many 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows users hit this error. crbug.com/69693 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Windows errors are unit32s, but all of likely errors are in 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // [1, 1000]. See winerror.h for the meaning of specific values. 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clip errors outside the expected range to a single extra value. 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there are errors in that extra bucket, we will know to expand 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the range. 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32 kMaxErrorToSend = 1001; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code = std::min(error_code, kMaxErrorToSend); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Extensions.ErrorCodeFromCrxOpen", 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code, kMaxErrorToSend); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_FILE_NOT_READABLE, 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_FILE_NOT_READABLE"))); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read and verify the header. 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appears that we don't have any endian/alignment aware serialization 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // code in the code base. So for now, this assumes that we're running 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on a little endian machine with 4 byte alignment. 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrxFile::Header header; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len = fread(&header, 1, sizeof(header), file.get()); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < sizeof(header)) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid crx header 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_HEADER_INVALID, 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_HEADER_INVALID"))); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrxFile::Error error; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<CrxFile> crx(CrxFile::Parse(header, &error)); 474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!crx) { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (error) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kWrongMagic: 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_MAGIC_NUMBER_INVALID, 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_MAGIC_NUMBER_INVALID"))); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidVersion: 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bad version numer 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_VERSION_NUMBER_INVALID, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_VERSION_NUMBER_INVALID"))); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidKeyTooLarge: 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidSignatureTooLarge: 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Excessively large key or signature 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE"))); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidKeyTooSmall: 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Key length is zero 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_ZERO_KEY_LENGTH, 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_ZERO_KEY_LENGTH"))); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidSignatureTooSmall: 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signature length is zero 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_ZERO_SIGNATURE_LENGTH, 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH"))); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8> key; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.resize(header.key_size); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = fread(&key.front(), sizeof(uint8), header.key_size, file.get()); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < header.key_size) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid public key 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_PUBLIC_KEY_INVALID, 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID"))); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8> signature; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signature.resize(header.signature_size); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = fread(&signature.front(), sizeof(uint8), header.signature_size, 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file.get()); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < header.signature_size) { 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid signature 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_SIGNATURE_INVALID, 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_SIGNATURE_INVALID"))); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::SignatureVerifier verifier; 5486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!verifier.VerifyInit(crx_file::kSignatureAlgorithm, 5496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sizeof(crx_file::kSignatureAlgorithm), 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &signature.front(), 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signature.size(), 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &key.front(), 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.size())) { 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signature verification initialization failed. This is most likely 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caused by a public key in the wrong format (should encode algorithm). 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED, 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED"))); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char buf[1 << 12]; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verifier.VerifyUpdate(buf, len); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!verifier.VerifyFinal()) { 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signature verification failed 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_SIGNATURE_VERIFICATION_FAILED, 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED"))); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string public_key = 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(reinterpret_cast<char*>(&key.front()), key.size()); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Base64Encode(public_key, &public_key_); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 58203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension_id_ = crx_file::id_util::GenerateId(public_key); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::ReportFailure(FailureReason reason, 588a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& error) { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason, NUM_FAILURE_REASONS); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackFailureTime", 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - unpack_start_time_); 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Cleanup(); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_->OnUnpackFailure(error); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::ReportSuccess( 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue& original_manifest, 5997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const SkBitmap& install_icon) { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccess", 1); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordSuccessfulUnpackTimeHistograms( 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crx_path_, base::TimeTicks::Now() - unpack_start_time_); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Client takes ownership of temporary directory and extension. 606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) client_->OnUnpackSuccess( 6077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch temp_dir_.Take(), extension_root_, &original_manifest, extension_.get(), 6087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch install_icon); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_ = NULL; 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::DictionaryValue* SandboxedUnpacker::RewriteManifestFile( 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue& manifest) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the public key extracted earlier to the parsed manifest and overwrite 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original manifest. We do this to ensure the manifest doesn't contain an 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exploitable bug that could be used to compromise the browser. 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> final_manifest(manifest.DeepCopy()); 6183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) final_manifest->SetString(manifest_keys::kPublicKey, public_key_); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string manifest_json; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONStringValueSerializer serializer(&manifest_json); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serializer.set_pretty_print(true); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!serializer.Serialize(*final_manifest)) { 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error serializing manifest.json. 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SERIALIZING_MANIFEST_JSON, 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SERIALIZING_MANIFEST_JSON"))); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath manifest_path = 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_root_.Append(kManifestFilename); 6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int size = base::checked_cast<int>(manifest_json.size()); 636a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::WriteFile(manifest_path, manifest_json.data(), size) != size) { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error saving manifest.json. 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SAVING_MANIFEST_JSON, 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SAVING_MANIFEST_JSON"))); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return final_manifest.release(); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool SandboxedUnpacker::RewriteImageFiles(SkBitmap* install_icon) { 6507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DecodedImages images; 6517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!ReadImagesFromFile(temp_dir_.path(), &images)) { 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Couldn't read image data from disk. 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_READ_IMAGE_DATA_FROM_DISK, 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("COULD_NOT_READ_IMAGE_DATA_FROM_DISK"))); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete any images that may be used by the browser. We're going to write 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // out our own versions of the parsed images, and we want to make sure the 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // originals are gone for good. 664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::set<base::FilePath> image_paths = 665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_file_util::GetBrowserImagePaths(extension_.get()); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_paths.size() != images.size()) { 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Decoded images don't match what's in the manifest. 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST, 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST"))); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::set<base::FilePath>::iterator it = image_paths.begin(); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != image_paths.end(); ++it) { 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = *it; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path.IsAbsolute() || path.ReferencesParent()) { 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid path for browser image. 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_PATH_FOR_BROWSER_IMAGE, 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE"))); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DeleteFile(extension_root_.Append(path), false)) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error removing old image file. 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_REMOVING_OLD_IMAGE_FILE, 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE"))); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& install_icon_path = 7001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IconsInfo::GetIcons(extension_.get()).Get( 7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_misc::EXTENSION_ICON_LARGE, ExtensionIconSet::MATCH_BIGGER); 7027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write our parsed images back to disk as well. 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < images.size(); ++i) { 7057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (BrowserThread::GetBlockingPool()->IsShutdownInProgress()) { 7067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Abort package installation if shutdown was initiated, crbug.com/235525 7077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ReportFailure( 7087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ABORTED_DUE_TO_SHUTDOWN, 7097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch l10n_util::GetStringFUTF16( 7107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASCIIToUTF16("ABORTED_DUE_TO_SHUTDOWN"))); 7127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 7137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 7147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap& image = images[i].a; 7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path_suffix = images[i].b; 7177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (path_suffix.MaybeAsASCII() == install_icon_path) 7187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *install_icon = image; 7197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) { 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid path for bitmap image. 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_PATH_FOR_BITMAP_IMAGE, 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("INVALID_PATH_FOR_BITMAP_IMAGE"))); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = extension_root_.Append(path_suffix); 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<unsigned char> image_data; 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // though they may originally be .jpg, etc. Figure something out. 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://code.google.com/p/chromium/issues/detail?id=12459 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) { 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error re-encoding theme image. 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_RE_ENCODING_THEME_IMAGE, 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE"))); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: we're overwriting existing files that the utility process wrote, 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so we can be sure the directory exists. 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]); 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int size = base::checked_cast<int>(image_data.size()); 749a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::WriteFile(path, image_data_ptr, size) != size) { 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error saving theme image. 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SAVING_THEME_IMAGE, 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE"))); 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SandboxedUnpacker::RewriteCatalogFiles() { 7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue catalogs; 7657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!ReadMessageCatalogsFromFile(temp_dir_.path(), &catalogs)) { 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Could not read catalog data from disk. 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_READ_CATALOG_DATA_FROM_DISK, 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("COULD_NOT_READ_CATALOG_DATA_FROM_DISK"))); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write our parsed catalogs back to disk. 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (base::DictionaryValue::Iterator it(catalogs); 7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !it.IsAtEnd(); it.Advance()) { 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* catalog = NULL; 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!it.value().GetAsDictionary(&catalog)) { 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid catalog data. 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_CATALOG_DATA, 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("INVALID_CATALOG_DATA"))); 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 78958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::FilePath relative_path = base::FilePath::FromUTF8Unsafe(it.key()); 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) relative_path = relative_path.Append(kMessagesFilename); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (relative_path.IsAbsolute() || relative_path.ReferencesParent()) { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid path for catalog. 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_PATH_FOR_CATALOG, 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("INVALID_PATH_FOR_CATALOG"))); 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = extension_root_.Append(relative_path); 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string catalog_json; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONStringValueSerializer serializer(&catalog_json); 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serializer.set_pretty_print(true); 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!serializer.Serialize(*catalog)) { 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error serializing catalog. 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SERIALIZING_CATALOG, 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SERIALIZING_CATALOG"))); 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: we're overwriting existing files that the utility process read, 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so we can be sure the directory exists. 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int size = base::checked_cast<int>(catalog_json.size()); 818a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::WriteFile(path, catalog_json.c_str(), size) != size) { 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error saving catalog. 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SAVING_CATALOG, 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SAVING_CATALOG"))); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SandboxedUnpacker::Cleanup() { 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!temp_dir_.Delete()) { 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Can not delete temp directory at " 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << temp_dir_.path().value(); 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 841