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) 57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/utility/extensions/unpacker.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_file_value_serializer.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/numerics/safe_conversions.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/common/chrome_utility_messages.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/i18n/default_locale_handler.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_file_util.h" 226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/child/image_decoder_utils.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/common_param_traits.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h" 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension_l10n_util.h" 28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/common/file_util.h" 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h" 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_utils.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/file_stream.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/zlib/google/zip.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/size.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace extensions { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace errors = manifest_errors; 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace keys = manifest_keys; 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A limit to stop us passing dangerously large canvases to the browser. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxImageCanvas = 4096 * 4096; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkBitmap DecodeImage(const base::FilePath& path) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read the file from disk. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string file_contents; 517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(path) || 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) !base::ReadFileToString(path, &file_contents)) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkBitmap(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Decode the image using WebKit's image decoder. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned char* data = 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const unsigned char*>(file_contents.data()); 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkBitmap bitmap = content::DecodeImage(data, 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gfx::Size(), 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch file_contents.length()); 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (bitmap.computeSize64() > kMaxImageCanvas) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkBitmap(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bitmap; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool PathContainsParentDirectory(const base::FilePath& path) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath::StringType kSeparators(base::FilePath::kSeparators); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath::StringType kParentDirectory( 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath::kParentDirectory); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t npos = base::FilePath::StringType::npos; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath::StringType& value = path.value(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < value.length(); ) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = value.find(kParentDirectory, i); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i != npos) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((i == 0 || kSeparators.find(value[i-1]) == npos) && 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (i+1 < value.length() || kSeparators.find(value[i+1]) == npos)) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool WritePickle(const IPC::Message& pickle, const base::FilePath& dest_path) { 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int size = base::checked_cast<int>(pickle.size()); 90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const char* data = static_cast<const char*>(pickle.data()); 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int bytes_written = base::WriteFile(dest_path, data, size); 92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return (bytes_written == size); 93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstruct Unpacker::InternalData { 987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DecodedImages decoded_images; 997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}; 1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Unpacker::Unpacker(const base::FilePath& extension_path, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Manifest::Location location, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int creation_flags) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : extension_path_(extension_path), 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_id_(extension_id), 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) location_(location), 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) creation_flags_(creation_flags) { 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch internal_data_.reset(new InternalData()); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Unpacker::~Unpacker() { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)base::DictionaryValue* Unpacker::ReadManifest() { 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath manifest_path = 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) temp_install_dir_.Append(kManifestFilename); 1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(manifest_path)) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError(errors::kInvalidManifest); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONFileValueSerializer serializer(manifest_path); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error; 1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error)); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!root.get()) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError(error); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!root->IsType(base::Value::TYPE_DICTIONARY)) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError(errors::kInvalidManifest); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return static_cast<base::DictionaryValue*>(root.release()); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Unpacker::ReadAllMessageCatalogs(const std::string& default_locale) { 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath locales_path = 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) temp_install_dir_.Append(kLocaleFolder); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not all folders under _locales have to be valid locales. 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator locales(locales_path, 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) false, 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator::DIRECTORIES); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> all_locales; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_l10n_util::GetAllLocales(&all_locales); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath locale_path; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!(locale_path = locales.Next()).empty()) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension_l10n_util::ShouldSkipValidation(locales_path, locale_path, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_locales)) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath messages_path = locale_path.Append(kMessagesFilename); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadMessageCatalog(messages_path)) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Unpacker::Run() { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Installing extension " << extension_path_.value(); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // <profile>/Extensions/CRX_INSTALL 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_install_dir_ = 170a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch extension_path_.DirName().AppendASCII(kTempExtensionName); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateDirectory(temp_install_dir_)) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetUTF16Error( 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_DIRECTORY_ERROR, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::i18n::GetDisplayStringInLTRDirectionality( 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_install_dir_.LossyDisplayName()))); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!zip::Unzip(extension_path_, temp_install_dir_)) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetUTF16Error(l10n_util::GetStringUTF16(IDS_EXTENSION_PACKAGE_UNZIP_ERROR)); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse the manifest. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parsed_manifest_.reset(ReadManifest()); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parsed_manifest_.get()) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Error was already reported. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<Extension> extension(Extension::Create( 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_install_dir_, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) location_, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *parsed_manifest_, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) creation_flags_, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_id_, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &error)); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension.get()) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError(error); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<InstallWarning> warnings; 205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!file_util::ValidateExtension(extension.get(), &error, &warnings)) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError(error); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension->AddInstallWarnings(warnings); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Decode any images that the browser needs to display. 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::set<base::FilePath> image_paths = 213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_file_util::GetBrowserImagePaths(extension.get()); 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::set<base::FilePath>::iterator it = image_paths.begin(); 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != image_paths.end(); 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ++it) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddDecodedImage(*it)) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Error was already reported. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse all message catalogs (if any). 2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) parsed_catalogs_.reset(new base::DictionaryValue); 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!LocaleInfo::GetDefaultLocale(extension.get()).empty()) { 224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!ReadAllMessageCatalogs(LocaleInfo::GetDefaultLocale(extension.get()))) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Error was already reported. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Unpacker::DumpImagesToFile() { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::Message pickle; // We use a Message so we can use WriteParam. 2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch IPC::WriteParam(&pickle, internal_data_->decoded_images); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = extension_path_.DirName().AppendASCII( 236a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch kDecodedImagesFilename); 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!WritePickle(pickle, path)) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError("Could not write image data to disk."); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Unpacker::DumpMessageCatalogsToFile() { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::Message pickle; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::WriteParam(&pickle, *parsed_catalogs_.get()); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = extension_path_.DirName().AppendASCII( 250a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch kDecodedMessageCatalogsFilename); 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!WritePickle(pickle, path)) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError("Could not write message catalogs to disk."); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Unpacker::AddDecodedImage(const base::FilePath& path) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure it's not referencing a file outside the extension's subdir. 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path.IsAbsolute() || PathContainsParentDirectory(path)) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetUTF16Error( 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_IMAGE_PATH_ERROR, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::i18n::GetDisplayStringInLTRDirectionality( 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.LossyDisplayName()))); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap image_bitmap = DecodeImage(temp_install_dir_.Append(path)); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_bitmap.isNull()) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetUTF16Error( 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16( 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_EXTENSION_PACKAGE_IMAGE_ERROR, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::i18n::GetDisplayStringInLTRDirectionality( 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.BaseName().LossyDisplayName()))); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch internal_data_->decoded_images.push_back(MakeTuple(image_bitmap, path)); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Unpacker::ReadMessageCatalog(const base::FilePath& message_path) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONFileValueSerializer serializer(message_path); 2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<base::DictionaryValue> root(static_cast<base::DictionaryValue*>( 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) serializer.Deserialize(NULL, &error))); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!root.get()) { 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 messages_file = message_path.LossyDisplayName(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error.empty()) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If file is missing, Deserialize will fail with empty error. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError(base::StringPrintf("%s %s", errors::kLocalesMessagesFileMissing, 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF16ToUTF8(messages_file).c_str())); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError(base::StringPrintf("%s: %s", 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF16ToUTF8(messages_file).c_str(), 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error.c_str())); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath relative_path; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message_path was created from temp_install_dir. This should never fail. 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!temp_install_dir_.AppendRelativePath(message_path, &relative_path)) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string dir_name = relative_path.DirName().MaybeAsASCII(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dir_name.empty()) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parsed_catalogs_->Set(dir_name, root.release()); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Unpacker::SetError(const std::string &error) { 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetUTF16Error(base::UTF8ToUTF16(error)); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Unpacker::SetUTF16Error(const base::string16& error) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_message_ = error; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 329