sandboxed_unpacker.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/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" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/utility_process_host.h" 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/common/common_param_traits.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/signature_verifier.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/crx_file.h" 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension_l10n_util.h" 37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/common/file_util.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/id_util.h" 393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest_constants.h" 40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::UtilityProcessHost; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following macro makes histograms that record the length of paths 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in this file much easier to read. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows has a short max path length. If the path length to a 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// file being unpacked from a CRX exceeds the max length, we might 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fail to install. To see if this is happening, see how long the 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// path to the temp unpack directory is. See crbug.com/69693 . 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PATH_LENGTH_HISTOGRAM(name, path) \ 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS(name, path.value().length(), 0, 500, 100) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Record a rate (kB per second) at which extensions are unpacked. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Range from 1kB/s to 100mB/s. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNPACK_RATE_HISTOGRAM(name, rate) \ 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS(name, rate, 1, 100000, 100); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace extensions { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecordSuccessfulUnpackTimeHistograms( 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& crx_path, const base::TimeDelta unpack_time) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int64 kBytesPerKb = 1024; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int64 kBytesPerMb = 1024 * 1024; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackSuccessTime", unpack_time); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To get a sense of how CRX size impacts unpack time, record unpack 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time for several increments of CRX size. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 crx_file_size; 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::GetFileSize(crx_path, &crx_file_size)) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccessCantGetCrxSize", 1); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cast is safe as long as the number of bytes in the CRX is less than 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2^31 * 2^10. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int crx_file_size_kb = static_cast<int>(crx_file_size / kBytesPerKb); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS( 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackSuccessCrxSize", crx_file_size_kb); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have time in seconds and file size in bytes. We want the rate bytes are 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unpacked in kB/s. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double file_size_kb = 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<double>(crx_file_size) / static_cast<double>(kBytesPerKb); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int unpack_rate_kb_per_s = 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(file_size_kb / unpack_time.InSecondsF()); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM("Extensions.SandboxUnpackRate", unpack_rate_kb_per_s); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crx_file_size < 50.0 * kBytesPerKb) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRateUnder50kB", unpack_rate_kb_per_s); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (crx_file_size < 1 * kBytesPerMb) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRate50kBTo1mB", unpack_rate_kb_per_s); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (crx_file_size < 2 * kBytesPerMb) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRate1To2mB", unpack_rate_kb_per_s); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (crx_file_size < 5 * kBytesPerMb) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRate2To5mB", unpack_rate_kb_per_s); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (crx_file_size < 10 * kBytesPerMb) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRate5To10mB", unpack_rate_kb_per_s); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACK_RATE_HISTOGRAM( 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Extensions.SandboxUnpackRateOver10mB", unpack_rate_kb_per_s); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Work horse for FindWritableTempLocation. Creates a temp file in the folder 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and uses NormalizeFilePath to check if the path is junction free. 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VerifyJunctionFreeLocation(base::FilePath* temp_dir) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (temp_dir->empty()) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath temp_file; 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateTemporaryFileInDir(*temp_dir, &temp_file)) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << temp_dir->value() << " is not writable"; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NormalizeFilePath requires a non-empty file, so write some data. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If you change the exit points of this function please make sure all 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exit points delete this temp file! 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::WriteFile(temp_file, ".", 1) != 1) 138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath normalized_temp_file; 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool normalized = base::NormalizeFilePath(temp_file, &normalized_temp_file); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!normalized) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |temp_file| contains a link, the sandbox will block al file system 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operations, and the install will fail. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << temp_dir->value() << " seem to be on remote drive."; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *temp_dir = normalized_temp_file.DirName(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clean up the temp file. 1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(temp_file, false); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return normalized; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function tries to find a location for unpacking the extension archive 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that is writable and does not lie on a shared drive so that the sandboxed 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unpacking process can write there. If no such location exists we can not 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// proceed and should fail. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The result will be written to |temp_dir|. The function will write to this 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parameter even if it returns false. 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FindWritableTempLocation(const base::FilePath& extensions_dir, 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath* temp_dir) { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// On ChromeOS, we will only attempt to unpack extension in cryptohome (profile) 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// directory to provide additional security/privacy and speed up the rest of 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the extension install process. 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_CHROMEOS) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathService::Get(base::DIR_TEMP, temp_dir); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VerifyJunctionFreeLocation(temp_dir)) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch *temp_dir = file_util::GetInstallTempDir(extensions_dir); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VerifyJunctionFreeLocation(temp_dir)) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Neither paths is link free chances are good installation will fail. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Both the %TEMP% folder and the profile seem to be on " 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "remote drives or read-only. Installation can not complete!"; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Read the decoded images back from the file we saved them to. 1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// |extension_path| is the path to the extension we unpacked that wrote the 1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// data. Returns true on success. 1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool ReadImagesFromFile(const base::FilePath& extension_path, 1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DecodedImages* images) { 1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::FilePath path = 187a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch extension_path.AppendASCII(kDecodedImagesFilename); 1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string file_str; 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!base::ReadFileToString(path, &file_str)) 1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch IPC::Message pickle(file_str.data(), file_str.size()); 1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PickleIterator iter(pickle); 1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return IPC::ReadParam(&pickle, &iter, images); 1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Read the decoded message catalogs back from the file we saved them to. 1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// |extension_path| is the path to the extension we unpacked that wrote the 1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// data. Returns true on success. 2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool ReadMessageCatalogsFromFile(const base::FilePath& extension_path, 2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DictionaryValue* catalogs) { 2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::FilePath path = extension_path.AppendASCII( 203a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch kDecodedMessageCatalogsFilename); 2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string file_str; 20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!base::ReadFileToString(path, &file_str)) 2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch IPC::Message pickle(file_str.data(), file_str.size()); 2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PickleIterator iter(pickle); 2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return IPC::ReadParam(&pickle, &iter, catalogs); 2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SandboxedUnpacker::SandboxedUnpacker( 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& crx_path, 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Manifest::Location location, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int creation_flags, 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& extensions_dir, 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::SequencedTaskRunner* unpacker_io_task_runner, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SandboxedUnpackerClient* client) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : crx_path_(crx_path), 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_(client), 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions_dir_(extensions_dir), 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_response_(false), 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) location_(location), 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) creation_flags_(creation_flags), 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unpacker_io_task_runner_(unpacker_io_task_runner) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SandboxedUnpacker::CreateTempDirectory() { 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath temp_dir; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FindWritableTempLocation(extensions_dir_, &temp_dir)) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_GET_TEMP_DIRECTORY, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("COULD_NOT_GET_TEMP_DIRECTORY"))); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!temp_dir_.CreateUniqueTempDirUnderPath(temp_dir)) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_CREATE_TEMP_DIRECTORY, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("COULD_NOT_CREATE_TEMP_DIRECTORY"))); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::Start() { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We assume that we are started on the thread that the client wants us to do 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file IO on. 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unpack_start_time_ = base::TimeTicks::Now(); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackInitialCrxPathLength", 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crx_path_); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateTempDirectory()) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // ReportFailure() already called. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the path that will eventually contain the unpacked extension. 269a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch extension_root_ = temp_dir_.path().AppendASCII(kTempExtensionName); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackUnpackedCrxPathLength", 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_root_); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Extract the public key and validate the package. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ValidateSignature()) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // ValidateSignature() already reported the error. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the crx file into our working directory. 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath temp_crx_path = temp_dir_.path().Append(crx_path_.BaseName()); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackTempCrxPathLength", 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_crx_path); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::CopyFile(crx_path_, temp_crx_path)) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Failed to copy extension file to temporary directory. 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY"))); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The utility process will have access to the directory passed to 2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SandboxedUnpacker. That directory should not contain a symlink or NTFS 2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // reparse point. When the path is used, following the link/reparse point 2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // will cause file system access outside the sandbox path, and the sandbox 2967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // will deny the operation. 2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::FilePath link_free_crx_path; 298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::NormalizeFilePath(temp_crx_path, &link_free_crx_path)) { 2997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch LOG(ERROR) << "Could not get the normalized path of " 3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch << temp_crx_path.value(); 3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ReportFailure( 3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch COULD_NOT_GET_SANDBOX_FRIENDLY_PATH, 3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch l10n_util::GetStringUTF16(IDS_EXTENSION_UNPACK_FAILED)); 3047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PATH_LENGTH_HISTOGRAM("Extensions.SandboxUnpackLinkFreeCrxPathLength", 3077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch link_free_crx_path); 3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BrowserThread::PostTask( 3107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BrowserThread::IO, FROM_HERE, 3117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Bind( 3127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &SandboxedUnpacker::StartProcessOnIOThread, 3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this, 3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch link_free_crx_path)); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SandboxedUnpacker::~SandboxedUnpacker() { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SandboxedUnpacker::OnMessageReceived(const IPC::Message& message) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(SandboxedUnpacker, message) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackExtension_Succeeded, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnUnpackExtensionSucceeded) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackExtension_Failed, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnUnpackExtensionFailed) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_END_MESSAGE_MAP() 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handled; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::OnProcessCrashed(int exit_code) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't report crashes if they happen after we got a response. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (got_response_) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Utility process crashed while trying to install. 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL, 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) + 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASCIIToUTF16(". ") + 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_PROCESS_CRASHED)); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SandboxedUnpacker::StartProcessOnIOThread( 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& temp_crx_path) { 349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UtilityProcessHost* host = 350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UtilityProcessHost::Create(this, unpacker_io_task_runner_.get()); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Grant the subprocess access to the entire subdir the extension file is 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in, so that it can unpack to that dir. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->SetExposedDir(temp_crx_path.DirName()); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->Send( 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ChromeUtilityMsg_UnpackExtension( 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_crx_path, extension_id_, location_, creation_flags_)); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::OnUnpackExtensionSucceeded( 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue& manifest) { 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_response_ = true; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> final_manifest( 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RewriteManifestFile(manifest)); 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!final_manifest) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an extension object that refers to the temporary location the 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extension was unpacked to. We use this until the extension is finally 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // installed. For example, the install UI shows images from inside the 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extension. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Localize manifest now, so confirm UI gets correct extension name. 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rdevlin.cronin): Continue removing std::string errors and replacing 377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // with base::string16 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string utf8_error; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_l10n_util::LocalizeExtension(extension_root_, 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final_manifest.get(), 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &utf8_error)) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_LOCALIZE_EXTENSION, 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(utf8_error))); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_ = Extension::Create( 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_root_, 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) location_, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *final_manifest, 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Extension::REQUIRE_KEY | creation_flags_, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &utf8_error); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!extension_.get()) { 398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ReportFailure(INVALID_MANIFEST, 399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASCIIToUTF16("Manifest is invalid: " + utf8_error)); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SkBitmap install_icon; 4047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!RewriteImageFiles(&install_icon)) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RewriteCatalogFiles()) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ReportSuccess(manifest, install_icon); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SandboxedUnpacker::OnUnpackExtensionFailed(const base::string16& error) { 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_response_ = true; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNPACKER_CLIENT_FAILED, 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error)); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SandboxedUnpacker::ValidateSignature() { 424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::ScopedFILE file(base::OpenFile(crx_path_, "rb")); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file.get()) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Could not open crx file for reading. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined (OS_WIN) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On windows, get the error code. 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 error_code = ::GetLastError(); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(skerner): Use this histogram to understand why so many 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows users hit this error. crbug.com/69693 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Windows errors are unit32s, but all of likely errors are in 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // [1, 1000]. See winerror.h for the meaning of specific values. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clip errors outside the expected range to a single extra value. 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there are errors in that extra bucket, we will know to expand 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the range. 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32 kMaxErrorToSend = 1001; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code = std::min(error_code, kMaxErrorToSend); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Extensions.ErrorCodeFromCrxOpen", 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code, kMaxErrorToSend); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_FILE_NOT_READABLE, 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_FILE_NOT_READABLE"))); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read and verify the header. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appears that we don't have any endian/alignment aware serialization 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // code in the code base. So for now, this assumes that we're running 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on a little endian machine with 4 byte alignment. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrxFile::Header header; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len = fread(&header, 1, sizeof(header), file.get()); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < sizeof(header)) { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid crx header 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_HEADER_INVALID, 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_HEADER_INVALID"))); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrxFile::Error error; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<CrxFile> crx(CrxFile::Parse(header, &error)); 472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!crx) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (error) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kWrongMagic: 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_MAGIC_NUMBER_INVALID, 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_MAGIC_NUMBER_INVALID"))); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidVersion: 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bad version numer 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_VERSION_NUMBER_INVALID, 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_VERSION_NUMBER_INVALID"))); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidKeyTooLarge: 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidSignatureTooLarge: 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Excessively large key or signature 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE, 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE"))); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidKeyTooSmall: 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Key length is zero 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_ZERO_KEY_LENGTH, 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_ZERO_KEY_LENGTH"))); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CrxFile::kInvalidSignatureTooSmall: 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signature length is zero 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_ZERO_SIGNATURE_LENGTH, 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_ZERO_SIGNATURE_LENGTH"))); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8> key; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.resize(header.key_size); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = fread(&key.front(), sizeof(uint8), header.key_size, file.get()); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < header.key_size) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid public key 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_PUBLIC_KEY_INVALID, 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_PUBLIC_KEY_INVALID"))); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8> signature; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signature.resize(header.signature_size); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = fread(&signature.front(), sizeof(uint8), header.signature_size, 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file.get()); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < header.signature_size) { 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid signature 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_SIGNATURE_INVALID, 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_SIGNATURE_INVALID"))); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::SignatureVerifier verifier; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!verifier.VerifyInit(extension_misc::kSignatureAlgorithm, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(extension_misc::kSignatureAlgorithm), 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &signature.front(), 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signature.size(), 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &key.front(), 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.size())) { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signature verification initialization failed. This is most likely 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caused by a public key in the wrong format (should encode algorithm). 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED, 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED"))); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char buf[1 << 12]; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verifier.VerifyUpdate(buf, len); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!verifier.VerifyFinal()) { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signature verification failed 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRX_SIGNATURE_VERIFICATION_FAILED, 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_ERROR_CODE, 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("CRX_SIGNATURE_VERIFICATION_FAILED"))); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string public_key = 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(reinterpret_cast<char*>(&key.front()), key.size()); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Base64Encode(public_key, &public_key_); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_id_ = id_util::GenerateId(public_key); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::ReportFailure(FailureReason reason, 586a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& error) { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason, NUM_FAILURE_REASONS); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackFailureTime", 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - unpack_start_time_); 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Cleanup(); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_->OnUnpackFailure(error); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SandboxedUnpacker::ReportSuccess( 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue& original_manifest, 5977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const SkBitmap& install_icon) { 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccess", 1); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordSuccessfulUnpackTimeHistograms( 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crx_path_, base::TimeTicks::Now() - unpack_start_time_); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Client takes ownership of temporary directory and extension. 604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) client_->OnUnpackSuccess( 6057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch temp_dir_.Take(), extension_root_, &original_manifest, extension_.get(), 6067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch install_icon); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_ = NULL; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::DictionaryValue* SandboxedUnpacker::RewriteManifestFile( 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue& manifest) { 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the public key extracted earlier to the parsed manifest and overwrite 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original manifest. We do this to ensure the manifest doesn't contain an 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exploitable bug that could be used to compromise the browser. 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> final_manifest(manifest.DeepCopy()); 6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) final_manifest->SetString(manifest_keys::kPublicKey, public_key_); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string manifest_json; 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONStringValueSerializer serializer(&manifest_json); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serializer.set_pretty_print(true); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!serializer.Serialize(*final_manifest)) { 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error serializing manifest.json. 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SERIALIZING_MANIFEST_JSON, 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SERIALIZING_MANIFEST_JSON"))); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath manifest_path = 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_root_.Append(kManifestFilename); 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int size = base::checked_cast<int>(manifest_json.size()); 634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::WriteFile(manifest_path, manifest_json.data(), size) != size) { 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error saving manifest.json. 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SAVING_MANIFEST_JSON, 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SAVING_MANIFEST_JSON"))); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return final_manifest.release(); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool SandboxedUnpacker::RewriteImageFiles(SkBitmap* install_icon) { 6487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DecodedImages images; 6497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!ReadImagesFromFile(temp_dir_.path(), &images)) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Couldn't read image data from disk. 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_READ_IMAGE_DATA_FROM_DISK, 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("COULD_NOT_READ_IMAGE_DATA_FROM_DISK"))); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete any images that may be used by the browser. We're going to write 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // out our own versions of the parsed images, and we want to make sure the 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // originals are gone for good. 662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::set<base::FilePath> image_paths = 663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_file_util::GetBrowserImagePaths(extension_.get()); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_paths.size() != images.size()) { 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Decoded images don't match what's in the manifest. 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST, 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST"))); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::set<base::FilePath>::iterator it = image_paths.begin(); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != image_paths.end(); ++it) { 6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = *it; 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path.IsAbsolute() || path.ReferencesParent()) { 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid path for browser image. 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_PATH_FOR_BROWSER_IMAGE, 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("INVALID_PATH_FOR_BROWSER_IMAGE"))); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DeleteFile(extension_root_.Append(path), false)) { 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error removing old image file. 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_REMOVING_OLD_IMAGE_FILE, 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_REMOVING_OLD_IMAGE_FILE"))); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string install_icon_path = IconsInfo::GetIcons(extension_).Get( 6987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch extension_misc::EXTENSION_ICON_LARGE, 6997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ExtensionIconSet::MATCH_BIGGER); 7007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write our parsed images back to disk as well. 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < images.size(); ++i) { 7037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (BrowserThread::GetBlockingPool()->IsShutdownInProgress()) { 7047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Abort package installation if shutdown was initiated, crbug.com/235525 7057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ReportFailure( 7067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ABORTED_DUE_TO_SHUTDOWN, 7077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch l10n_util::GetStringFUTF16( 7087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASCIIToUTF16("ABORTED_DUE_TO_SHUTDOWN"))); 7107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 7117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 7127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap& image = images[i].a; 7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path_suffix = images[i].b; 7157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (path_suffix.MaybeAsASCII() == install_icon_path) 7167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *install_icon = image; 7177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_suffix.IsAbsolute() || path_suffix.ReferencesParent()) { 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid path for bitmap image. 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_PATH_FOR_BITMAP_IMAGE, 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("INVALID_PATH_FOR_BITMAP_IMAGE"))); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = extension_root_.Append(path_suffix); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<unsigned char> image_data; 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mpcomplete): It's lame that we're encoding all images as PNG, even 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // though they may originally be .jpg, etc. Figure something out. 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://code.google.com/p/chromium/issues/detail?id=12459 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data)) { 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error re-encoding theme image. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_RE_ENCODING_THEME_IMAGE, 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE"))); 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: we're overwriting existing files that the utility process wrote, 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so we can be sure the directory exists. 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]); 7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int size = base::checked_cast<int>(image_data.size()); 747a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::WriteFile(path, image_data_ptr, size) != size) { 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error saving theme image. 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SAVING_THEME_IMAGE, 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE"))); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SandboxedUnpacker::RewriteCatalogFiles() { 7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue catalogs; 7637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!ReadMessageCatalogsFromFile(temp_dir_.path(), &catalogs)) { 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Could not read catalog data from disk. 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COULD_NOT_READ_CATALOG_DATA_FROM_DISK, 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("COULD_NOT_READ_CATALOG_DATA_FROM_DISK"))); 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write our parsed catalogs back to disk. 7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (base::DictionaryValue::Iterator it(catalogs); 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !it.IsAtEnd(); it.Advance()) { 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* catalog = NULL; 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!it.value().GetAsDictionary(&catalog)) { 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid catalog data. 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_CATALOG_DATA, 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("INVALID_CATALOG_DATA"))); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 78758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::FilePath relative_path = base::FilePath::FromUTF8Unsafe(it.key()); 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) relative_path = relative_path.Append(kMessagesFilename); 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (relative_path.IsAbsolute() || relative_path.ReferencesParent()) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid path for catalog. 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_PATH_FOR_CATALOG, 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("INVALID_PATH_FOR_CATALOG"))); 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = extension_root_.Append(relative_path); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string catalog_json; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONStringValueSerializer serializer(&catalog_json); 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serializer.set_pretty_print(true); 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!serializer.Serialize(*catalog)) { 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error serializing catalog. 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SERIALIZING_CATALOG, 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SERIALIZING_CATALOG"))); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: we're overwriting existing files that the utility process read, 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so we can be sure the directory exists. 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int size = base::checked_cast<int>(catalog_json.size()); 816a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base::WriteFile(path, catalog_json.c_str(), size) != size) { 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error saving catalog. 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportFailure( 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SAVING_CATALOG, 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_INSTALL_ERROR, 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToUTF16("ERROR_SAVING_CATALOG"))); 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SandboxedUnpacker::Cleanup() { 8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!temp_dir_.Delete()) { 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Can not delete temp directory at " 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << temp_dir_.path().value(); 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 839