1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 28ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Use of this source code is governed by a BSD-style license that can be 38ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// found in the LICENSE file. 48ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 58ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension_unpacker.h" 68ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <set> 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 98ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/file_util.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_handle.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_temp_dir.h" 128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/string_util.h" 133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h" 148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/utf_string_conversions.h" 158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "base/values.h" 168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "net/base/file_stream.h" 178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension.h" 188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension_constants.h" 198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension_file_util.h" 208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/extensions/extension_l10n_util.h" 218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/url_constants.h" 228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "chrome/common/zip.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/common_param_traits.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/json_value_serializer.h" 258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "ipc/ipc_message_utils.h" 268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "third_party/skia/include/core/SkBitmap.h" 278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#include "webkit/glue/image_decoder.h" 288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsennamespace errors = extension_manifest_errors; 308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsennamespace keys = extension_manifest_keys; 318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsennamespace filenames = extension_filenames; 328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsennamespace { 348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// Errors 368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char* kCouldNotCreateDirectoryError = 378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen "Could not create directory for unzipping: "; 388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char* kCouldNotDecodeImageError = "Could not decode theme image."; 398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char* kCouldNotUnzipExtension = "Could not unzip extension."; 408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst char* kPathNamesMustBeAbsoluteOrLocalError = 418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen "Path names must not be absolute or contain '..'."; 428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// A limit to stop us passing dangerously large canvases to the browser. 448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenconst int kMaxImageCanvas = 4096 * 4096; 458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 468ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenSkBitmap DecodeImage(const FilePath& path) { 478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // Read the file from disk. 488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen std::string file_contents; 498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!file_util::PathExists(path) || 508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen !file_util::ReadFileToString(path, &file_contents)) { 518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return SkBitmap(); 528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // Decode the image using WebKit's image decoder. 558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen const unsigned char* data = 568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen reinterpret_cast<const unsigned char*>(file_contents.data()); 578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen webkit_glue::ImageDecoder decoder; 588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SkBitmap bitmap = decoder.Decode(data, file_contents.length()); 598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen Sk64 bitmap_size = bitmap.getSize64(); 608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!bitmap_size.is32() || bitmap_size.get32() > kMaxImageCanvas) 618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return SkBitmap(); 628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return bitmap; 638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool PathContainsParentDirectory(const FilePath& path) { 668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen const FilePath::StringType kSeparators(FilePath::kSeparators); 678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen const FilePath::StringType kParentDirectory(FilePath::kParentDirectory); 688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen const size_t npos = FilePath::StringType::npos; 698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen const FilePath::StringType& value = path.value(); 708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (size_t i = 0; i < value.length(); ) { 728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen i = value.find(kParentDirectory, i); 738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (i != npos) { 748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if ((i == 0 || kSeparators.find(value[i-1]) == npos) && 758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen (i+1 < value.length() || kSeparators.find(value[i+1]) == npos)) { 768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return true; 778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen ++i; 798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} // namespace 868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 878ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenExtensionUnpacker::ExtensionUnpacker(const FilePath& extension_path) 888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen : extension_path_(extension_path) { 898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 918ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenExtensionUnpacker::~ExtensionUnpacker() { 928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 948ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenDictionaryValue* ExtensionUnpacker::ReadManifest() { 958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen FilePath manifest_path = 968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen temp_install_dir_.Append(Extension::kManifestFilename); 978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!file_util::PathExists(manifest_path)) { 988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError(errors::kInvalidManifest); 998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return NULL; 1008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen JSONFileValueSerializer serializer(manifest_path); 1038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen std::string error; 1048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen scoped_ptr<Value> root(serializer.Deserialize(NULL, &error)); 1058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!root.get()) { 1068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError(error); 1078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return NULL; 1088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!root->IsType(Value::TYPE_DICTIONARY)) { 1118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError(errors::kInvalidManifest); 1128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return NULL; 1138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return static_cast<DictionaryValue*>(root.release()); 1168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 1178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool ExtensionUnpacker::ReadAllMessageCatalogs( 1198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen const std::string& default_locale) { 1208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen FilePath locales_path = 1218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen temp_install_dir_.Append(Extension::kLocaleFolder); 1228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // Not all folders under _locales have to be valid locales. 1248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen file_util::FileEnumerator locales(locales_path, 1258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen false, 1268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen file_util::FileEnumerator::DIRECTORIES); 1278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen std::set<std::string> all_locales; 1298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen extension_l10n_util::GetAllLocales(&all_locales); 1308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen FilePath locale_path; 1318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen while (!(locale_path = locales.Next()).empty()) { 1328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (extension_l10n_util::ShouldSkipValidation(locales_path, locale_path, 1338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen all_locales)) 1348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen continue; 1358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen FilePath messages_path = 1378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen locale_path.Append(Extension::kMessagesFilename); 1388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!ReadMessageCatalog(messages_path)) 1408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 1418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return true; 1448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 1458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool ExtensionUnpacker::Run() { 147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Installing extension " << extension_path_.value(); 1488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // <profile>/Extensions/INSTALL_TEMP/<version> 1508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen temp_install_dir_ = 1518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen extension_path_.DirName().AppendASCII(filenames::kTempExtensionName); 1528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!file_util::CreateDirectory(temp_install_dir_)) { 1548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#if defined(OS_WIN) 1558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen std::string dir_string = WideToUTF8(temp_install_dir_.value()); 1568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#else 1578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen std::string dir_string = temp_install_dir_.value(); 1588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen#endif 1598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError(kCouldNotCreateDirectoryError + dir_string); 1618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 1628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!Unzip(extension_path_, temp_install_dir_)) { 1658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError(kCouldNotUnzipExtension); 1668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 1678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // Parse the manifest. 1708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen parsed_manifest_.reset(ReadManifest()); 1718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!parsed_manifest_.get()) 1728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; // Error was already reported. 1738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // NOTE: Since the unpacker doesn't have the extension's public_id, the 1758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // InitFromValue is allowed to generate a temporary id for the extension. 1768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // ANY CODE THAT FOLLOWS SHOULD NOT DEPEND ON THE CORRECT ID OF THIS 1778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // EXTENSION. 1788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen std::string error; 179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<Extension> extension(Extension::Create( 180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen temp_install_dir_, 181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen Extension::INVALID, 182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen *parsed_manifest_, 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Extension::NO_FLAGS, 184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &error)); 185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!extension.get()) { 1868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError(error); 1878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 1888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!extension_file_util::ValidateExtension(extension.get(), &error)) { 1918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError(error); 1928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 1938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // Decode any images that the browser needs to display. 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::set<FilePath> image_paths = extension->GetBrowserImages(); 1978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (std::set<FilePath>::iterator it = image_paths.begin(); 1988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen it != image_paths.end(); ++it) { 1998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!AddDecodedImage(*it)) 2008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; // Error was already reported. 2018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // Parse all message catalogs (if any). 2048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen parsed_catalogs_.reset(new DictionaryValue); 205513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!extension->default_locale().empty()) { 206513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!ReadAllMessageCatalogs(extension->default_locale())) 2078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; // Error was already reported. 2088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return true; 2118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool ExtensionUnpacker::DumpImagesToFile() { 2148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen IPC::Message pickle; // We use a Message so we can use WriteParam. 2158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen IPC::WriteParam(&pickle, decoded_images_); 2168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen FilePath path = extension_path_.DirName().AppendASCII( 2188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen filenames::kDecodedImagesFilename); 2198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!file_util::WriteFile(path, static_cast<const char*>(pickle.data()), 2208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen pickle.size())) { 2218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError("Could not write image data to disk."); 2228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 2238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return true; 2268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool ExtensionUnpacker::DumpMessageCatalogsToFile() { 2298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen IPC::Message pickle; 2308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen IPC::WriteParam(&pickle, *parsed_catalogs_.get()); 2318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen FilePath path = extension_path_.DirName().AppendASCII( 2338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen filenames::kDecodedMessageCatalogsFilename); 2348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!file_util::WriteFile(path, static_cast<const char*>(pickle.data()), 2358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen pickle.size())) { 2368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError("Could not write message catalogs to disk."); 2378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 2388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return true; 2418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static 2448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool ExtensionUnpacker::ReadImagesFromFile(const FilePath& extension_path, 2458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen DecodedImages* images) { 2468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen FilePath path = extension_path.AppendASCII(filenames::kDecodedImagesFilename); 2478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen std::string file_str; 2488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!file_util::ReadFileToString(path, &file_str)) 2498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 2508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen IPC::Message pickle(file_str.data(), file_str.size()); 2528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen void* iter = NULL; 2538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return IPC::ReadParam(&pickle, &iter, images); 2548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen// static 2578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool ExtensionUnpacker::ReadMessageCatalogsFromFile( 2588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen const FilePath& extension_path, DictionaryValue* catalogs) { 2598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen FilePath path = extension_path.AppendASCII( 2608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen filenames::kDecodedMessageCatalogsFilename); 2618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen std::string file_str; 2628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!file_util::ReadFileToString(path, &file_str)) 2638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 2648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen IPC::Message pickle(file_str.data(), file_str.size()); 2668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen void* iter = NULL; 2678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return IPC::ReadParam(&pickle, &iter, catalogs); 2688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool ExtensionUnpacker::AddDecodedImage(const FilePath& path) { 2718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // Make sure it's not referencing a file outside the extension's subdir. 2728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (path.IsAbsolute() || PathContainsParentDirectory(path)) { 2738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError(kPathNamesMustBeAbsoluteOrLocalError); 2748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 2758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SkBitmap image_bitmap = DecodeImage(temp_install_dir_.Append(path)); 2788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (image_bitmap.isNull()) { 2798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen SetError(kCouldNotDecodeImageError); 2808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 2818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen decoded_images_.push_back(MakeTuple(image_bitmap, path)); 2848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return true; 2858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenbool ExtensionUnpacker::ReadMessageCatalog(const FilePath& message_path) { 2888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen std::string error; 2898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen JSONFileValueSerializer serializer(message_path); 2908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen scoped_ptr<DictionaryValue> root( 2918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen static_cast<DictionaryValue*>(serializer.Deserialize(NULL, &error))); 2928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!root.get()) { 293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen string16 messages_file = message_path.LossyDisplayName(); 2948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (error.empty()) { 2958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // If file is missing, Deserialize will fail with empty error. 296513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SetError(base::StringPrintf("%s %s", errors::kLocalesMessagesFileMissing, 297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UTF16ToUTF8(messages_file).c_str())); 2988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetError(base::StringPrintf("%s: %s", 300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UTF16ToUTF8(messages_file).c_str(), 301513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch error.c_str())); 3028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 3048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen FilePath relative_path; 3078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen // message_path was created from temp_install_dir. This should never fail. 308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!temp_install_dir_.AppendRelativePath(message_path, &relative_path)) { 3098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen NOTREACHED(); 310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 3128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string dir_name = relative_path.DirName().MaybeAsASCII(); 314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (dir_name.empty()) { 315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED(); 316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen parsed_catalogs_->Set(dir_name, root.release()); 3198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return true; 3218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 3228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvoid ExtensionUnpacker::SetError(const std::string &error) { 3248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen error_message_ = error; 3258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 326