Home | History | Annotate | Download | only in extensions
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/utility/extensions/extensions_handler.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/path_service.h"
      9 #include "chrome/common/chrome_utility_messages.h"
     10 #include "chrome/common/extensions/chrome_extensions_client.h"
     11 #include "chrome/common/extensions/chrome_utility_extensions_messages.h"
     12 #include "chrome/common/media_galleries/metadata_types.h"
     13 #include "chrome/utility/chrome_content_utility_client.h"
     14 #include "chrome/utility/extensions/unpacker.h"
     15 #include "chrome/utility/media_galleries/image_metadata_extractor.h"
     16 #include "content/public/common/content_paths.h"
     17 #include "content/public/utility/utility_thread.h"
     18 #include "extensions/common/extension.h"
     19 #include "extensions/common/extension_l10n_util.h"
     20 #include "extensions/common/extension_utility_messages.h"
     21 #include "extensions/common/manifest.h"
     22 #include "extensions/common/update_manifest.h"
     23 #include "media/base/media.h"
     24 #include "media/base/media_file_checker.h"
     25 #include "third_party/zlib/google/zip.h"
     26 #include "ui/base/ui_base_switches.h"
     27 
     28 #if defined(OS_WIN)
     29 #include "chrome/common/extensions/api/networking_private/networking_private_crypto.h"
     30 #include "chrome/utility/media_galleries/itunes_pref_parser_win.h"
     31 #include "components/wifi/wifi_service.h"
     32 #endif  // defined(OS_WIN)
     33 
     34 #if defined(OS_MACOSX)
     35 #include "chrome/utility/media_galleries/iphoto_library_parser.h"
     36 #endif  // defined(OS_MACOSX)
     37 
     38 #if defined(OS_WIN) || defined(OS_MACOSX)
     39 #include "chrome/utility/media_galleries/iapps_xml_utils.h"
     40 #include "chrome/utility/media_galleries/itunes_library_parser.h"
     41 #include "chrome/utility/media_galleries/picasa_album_table_reader.h"
     42 #include "chrome/utility/media_galleries/picasa_albums_indexer.h"
     43 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
     44 
     45 namespace extensions {
     46 
     47 namespace {
     48 
     49 bool Send(IPC::Message* message) {
     50   return content::UtilityThread::Get()->Send(message);
     51 }
     52 
     53 void ReleaseProcessIfNeeded() {
     54   content::UtilityThread::Get()->ReleaseProcessIfNeeded();
     55 }
     56 
     57 const char kExtensionHandlerUnzipError[] =
     58     "Could not unzip extension for install.";
     59 
     60 }  // namespace
     61 
     62 ExtensionsHandler::ExtensionsHandler() {
     63 }
     64 
     65 ExtensionsHandler::~ExtensionsHandler() {
     66 }
     67 
     68 // static
     69 void ExtensionsHandler::PreSandboxStartup() {
     70   // Initialize libexif for image metadata parsing.
     71   metadata::ImageMetadataExtractor::InitializeLibrary();
     72 
     73   // Load media libraries for media file validation.
     74   base::FilePath media_path;
     75   PathService::Get(content::DIR_MEDIA_LIBS, &media_path);
     76   if (!media_path.empty())
     77     media::InitializeMediaLibrary(media_path);
     78 }
     79 
     80 void ExtensionsHandler::UtilityThreadStarted() {
     81   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
     82   std::string lang = command_line->GetSwitchValueASCII(switches::kLang);
     83   if (!lang.empty())
     84     extension_l10n_util::SetProcessLocale(lang);
     85 }
     86 
     87 bool ExtensionsHandler::OnMessageReceived(const IPC::Message& message) {
     88   bool handled = true;
     89   IPC_BEGIN_MESSAGE_MAP(ExtensionsHandler, message)
     90     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnpackExtension, OnUnpackExtension)
     91     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnzipToDir, OnUnzipToDir)
     92     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_DecodeImageBase64, OnDecodeImageBase64)
     93     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseJSON, OnParseJSON)
     94     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CheckMediaFile, OnCheckMediaFile)
     95 #if defined(OS_WIN)
     96     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesPrefXml,
     97                         OnParseITunesPrefXml)
     98 #endif  // defined(OS_WIN)
     99 
    100 #if defined(OS_MACOSX)
    101     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseIPhotoLibraryXmlFile,
    102                         OnParseIPhotoLibraryXmlFile)
    103 #endif  // defined(OS_MACOSX)
    104 
    105 #if defined(OS_WIN) || defined(OS_MACOSX)
    106     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesLibraryXmlFile,
    107                         OnParseITunesLibraryXmlFile)
    108     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParsePicasaPMPDatabase,
    109                         OnParsePicasaPMPDatabase)
    110     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_IndexPicasaAlbumsContents,
    111                         OnIndexPicasaAlbumsContents)
    112 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
    113 
    114 #if defined(OS_WIN)
    115     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetWiFiCredentials,
    116                         OnGetWiFiCredentials)
    117 #endif  // defined(OS_WIN)
    118 
    119     IPC_MESSAGE_HANDLER(ExtensionUtilityMsg_ParseUpdateManifest,
    120                         OnParseUpdateManifest)
    121 
    122     IPC_MESSAGE_UNHANDLED(handled = false)
    123   IPC_END_MESSAGE_MAP()
    124   return handled;
    125 }
    126 
    127 void ExtensionsHandler::OnUnpackExtension(
    128     const base::FilePath& extension_path,
    129     const std::string& extension_id,
    130     int location,
    131     int creation_flags) {
    132   CHECK_GT(location, Manifest::INVALID_LOCATION);
    133   CHECK_LT(location, Manifest::NUM_LOCATIONS);
    134   ExtensionsClient::Set(ChromeExtensionsClient::GetInstance());
    135   Unpacker unpacker(extension_path,
    136                     extension_id,
    137                     static_cast<Manifest::Location>(location),
    138                     creation_flags);
    139   if (unpacker.Run() && unpacker.DumpImagesToFile() &&
    140       unpacker.DumpMessageCatalogsToFile()) {
    141     Send(new ChromeUtilityHostMsg_UnpackExtension_Succeeded(
    142         *unpacker.parsed_manifest()));
    143   } else {
    144     Send(new ChromeUtilityHostMsg_UnpackExtension_Failed(
    145         unpacker.error_message()));
    146   }
    147 
    148   ReleaseProcessIfNeeded();
    149 }
    150 
    151 void ExtensionsHandler::OnUnzipToDir(const base::FilePath& zip_path,
    152                                      const base::FilePath& dir) {
    153   if (!zip::Unzip(zip_path, dir)) {
    154     Send(new ChromeUtilityHostMsg_UnzipToDir_Failed(
    155         std::string(kExtensionHandlerUnzipError)));
    156   } else {
    157     Send(new ChromeUtilityHostMsg_UnzipToDir_Succeeded(dir));
    158   }
    159 
    160   ReleaseProcessIfNeeded();
    161 }
    162 
    163 void ExtensionsHandler::OnParseUpdateManifest(const std::string& xml) {
    164   UpdateManifest manifest;
    165   if (!manifest.Parse(xml)) {
    166     Send(new ExtensionUtilityHostMsg_ParseUpdateManifest_Failed(
    167         manifest.errors()));
    168   } else {
    169     Send(new ExtensionUtilityHostMsg_ParseUpdateManifest_Succeeded(
    170         manifest.results()));
    171   }
    172   ReleaseProcessIfNeeded();
    173 }
    174 
    175 void ExtensionsHandler::OnDecodeImageBase64(
    176     const std::string& encoded_string) {
    177   std::string decoded_string;
    178 
    179   if (!base::Base64Decode(encoded_string, &decoded_string)) {
    180     Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
    181     return;
    182   }
    183 
    184   std::vector<unsigned char> decoded_vector(decoded_string.size());
    185   for (size_t i = 0; i < decoded_string.size(); ++i) {
    186     decoded_vector[i] = static_cast<unsigned char>(decoded_string[i]);
    187   }
    188 
    189   ChromeContentUtilityClient::DecodeImageAndSend(decoded_vector, false);
    190 }
    191 
    192 void ExtensionsHandler::OnParseJSON(const std::string& json) {
    193   int error_code;
    194   std::string error;
    195   base::Value* value = base::JSONReader::ReadAndReturnError(
    196       json, base::JSON_PARSE_RFC, &error_code, &error);
    197   if (value) {
    198     base::ListValue wrapper;
    199     wrapper.Append(value);
    200     Send(new ChromeUtilityHostMsg_ParseJSON_Succeeded(wrapper));
    201   } else {
    202     Send(new ChromeUtilityHostMsg_ParseJSON_Failed(error));
    203   }
    204   ReleaseProcessIfNeeded();
    205 }
    206 
    207 void ExtensionsHandler::OnCheckMediaFile(
    208     int64 milliseconds_of_decoding,
    209     const IPC::PlatformFileForTransit& media_file) {
    210   media::MediaFileChecker checker(
    211       IPC::PlatformFileForTransitToFile(media_file));
    212   const bool check_success = checker.Start(
    213       base::TimeDelta::FromMilliseconds(milliseconds_of_decoding));
    214   Send(new ChromeUtilityHostMsg_CheckMediaFile_Finished(check_success));
    215   ReleaseProcessIfNeeded();
    216 }
    217 
    218 #if defined(OS_WIN)
    219 void ExtensionsHandler::OnParseITunesPrefXml(
    220     const std::string& itunes_xml_data) {
    221   base::FilePath library_path(
    222       itunes::FindLibraryLocationInPrefXml(itunes_xml_data));
    223   Send(new ChromeUtilityHostMsg_GotITunesDirectory(library_path));
    224   ReleaseProcessIfNeeded();
    225 }
    226 #endif  // defined(OS_WIN)
    227 
    228 #if defined(OS_MACOSX)
    229 void ExtensionsHandler::OnParseIPhotoLibraryXmlFile(
    230     const IPC::PlatformFileForTransit& iphoto_library_file) {
    231   iphoto::IPhotoLibraryParser parser;
    232   base::File file = IPC::PlatformFileForTransitToFile(iphoto_library_file);
    233   bool result = parser.Parse(iapps::ReadFileAsString(file.Pass()));
    234   Send(new ChromeUtilityHostMsg_GotIPhotoLibrary(result, parser.library()));
    235   ReleaseProcessIfNeeded();
    236 }
    237 #endif  // defined(OS_MACOSX)
    238 
    239 #if defined(OS_WIN) || defined(OS_MACOSX)
    240 void ExtensionsHandler::OnParseITunesLibraryXmlFile(
    241     const IPC::PlatformFileForTransit& itunes_library_file) {
    242   itunes::ITunesLibraryParser parser;
    243   base::File file = IPC::PlatformFileForTransitToFile(itunes_library_file);
    244   bool result = parser.Parse(iapps::ReadFileAsString(file.Pass()));
    245   Send(new ChromeUtilityHostMsg_GotITunesLibrary(result, parser.library()));
    246   ReleaseProcessIfNeeded();
    247 }
    248 
    249 void ExtensionsHandler::OnParsePicasaPMPDatabase(
    250     const picasa::AlbumTableFilesForTransit& album_table_files) {
    251   picasa::AlbumTableFiles files;
    252   files.indicator_file =
    253       IPC::PlatformFileForTransitToFile(album_table_files.indicator_file);
    254   files.category_file =
    255       IPC::PlatformFileForTransitToFile(album_table_files.category_file);
    256   files.date_file =
    257       IPC::PlatformFileForTransitToFile(album_table_files.date_file);
    258   files.filename_file =
    259       IPC::PlatformFileForTransitToFile(album_table_files.filename_file);
    260   files.name_file =
    261       IPC::PlatformFileForTransitToFile(album_table_files.name_file);
    262   files.token_file =
    263       IPC::PlatformFileForTransitToFile(album_table_files.token_file);
    264   files.uid_file =
    265       IPC::PlatformFileForTransitToFile(album_table_files.uid_file);
    266 
    267   picasa::PicasaAlbumTableReader reader(files.Pass());
    268   bool parse_success = reader.Init();
    269   Send(new ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished(
    270       parse_success, reader.albums(), reader.folders()));
    271   ReleaseProcessIfNeeded();
    272 }
    273 
    274 void ExtensionsHandler::OnIndexPicasaAlbumsContents(
    275     const picasa::AlbumUIDSet& album_uids,
    276     const std::vector<picasa::FolderINIContents>& folders_inis) {
    277   picasa::PicasaAlbumsIndexer indexer(album_uids);
    278   indexer.ParseFolderINI(folders_inis);
    279 
    280   Send(new ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished(
    281       indexer.albums_images()));
    282   ReleaseProcessIfNeeded();
    283 }
    284 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
    285 
    286 #if defined(OS_WIN)
    287 void ExtensionsHandler::OnGetWiFiCredentials(const std::string& network_guid) {
    288   scoped_ptr<wifi::WiFiService> wifi_service(wifi::WiFiService::Create());
    289   wifi_service->Initialize(NULL);
    290 
    291   std::string key_data;
    292   std::string error;
    293   wifi_service->GetKeyFromSystem(network_guid, &key_data, &error);
    294 
    295   Send(new ChromeUtilityHostMsg_GotWiFiCredentials(key_data, error.empty()));
    296 }
    297 #endif  // defined(OS_WIN)
    298 
    299 }  // namespace extensions
    300