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 45namespace extensions { 46 47namespace { 48 49bool Send(IPC::Message* message) { 50 return content::UtilityThread::Get()->Send(message); 51} 52 53void ReleaseProcessIfNeeded() { 54 content::UtilityThread::Get()->ReleaseProcessIfNeeded(); 55} 56 57const char kExtensionHandlerUnzipError[] = 58 "Could not unzip extension for install."; 59 60} // namespace 61 62ExtensionsHandler::ExtensionsHandler() { 63} 64 65ExtensionsHandler::~ExtensionsHandler() { 66} 67 68// static 69void 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 80void 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 87bool 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 127void 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 151void 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 163void 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 175void 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 192void 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 207void 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) 219void 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) 229void 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) 240void 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 249void 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 274void 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) 287void 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