1 // Copyright 2013 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/browser/media_galleries/imported_media_gallery_registry.h" 6 7 #include "base/bind.h" 8 #include "base/files/file_util.h" 9 #include "base/logging.h" 10 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h" 11 #include "chrome/browser/media_galleries/fileapi/itunes_data_provider.h" 12 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" 13 #include "chrome/browser/media_galleries/fileapi/picasa_data_provider.h" 14 #include "chrome/common/extensions/extension_constants.h" 15 #include "content/public/browser/browser_thread.h" 16 #include "storage/browser/fileapi/external_mount_points.h" 17 #include "storage/common/fileapi/file_system_mount_option.h" 18 19 using base::Bind; 20 using storage::ExternalMountPoints; 21 22 namespace { 23 24 static base::LazyInstance<ImportedMediaGalleryRegistry>::Leaky 25 g_imported_media_gallery_registry = LAZY_INSTANCE_INITIALIZER; 26 27 } // namespace 28 29 // static 30 ImportedMediaGalleryRegistry* ImportedMediaGalleryRegistry::GetInstance() { 31 return g_imported_media_gallery_registry.Pointer(); 32 } 33 34 void ImportedMediaGalleryRegistry::Initialize() { 35 base::ThreadRestrictions::AssertIOAllowed(); 36 if (imported_root_.empty()) { 37 if (!base::CreateTemporaryFile(&imported_root_)) 38 imported_root_ = base::FilePath(); 39 // TODO(vandebo) Setting the permissions of |imported_root_| in CPSP to 40 // zero would be an extra step to ensure permissions are correctly 41 // enforced. 42 } 43 } 44 45 bool ImportedMediaGalleryRegistry::RegisterPicasaFilesystemOnUIThread( 46 const std::string& fs_name, const base::FilePath& database_path) { 47 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 48 DCHECK(!fs_name.empty()); 49 DCHECK(!database_path.empty()); 50 51 bool result = false; 52 53 #if defined(OS_WIN) || defined(OS_MACOSX) 54 base::FilePath root = ImportedRoot(); 55 if (root.empty()) 56 return false; 57 result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( 58 fs_name, 59 storage::kFileSystemTypePicasa, 60 storage::FileSystemMountOption(), 61 root.AppendASCII("picasa")); 62 if (!result) 63 return result; 64 65 picasa_fs_names_.insert(fs_name); 66 67 if (picasa_fs_names_.size() == 1) { 68 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 69 FROM_HERE, 70 Bind(&ImportedMediaGalleryRegistry::RegisterPicasaFileSystem, 71 base::Unretained(this), database_path)); 72 #ifndef NDEBUG 73 picasa_database_path_ = database_path; 74 } else { 75 DCHECK_EQ(picasa_database_path_.value(), database_path.value()); 76 #endif 77 } 78 #endif // defined(OS_WIN) || defined(OS_MACOSX) 79 80 return result; 81 } 82 83 bool ImportedMediaGalleryRegistry::RegisterITunesFilesystemOnUIThread( 84 const std::string& fs_name, const base::FilePath& library_xml_path) { 85 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 86 DCHECK(!library_xml_path.empty()); 87 88 bool result = false; 89 90 #if defined(OS_WIN) || defined(OS_MACOSX) 91 base::FilePath root = ImportedRoot(); 92 if (root.empty()) 93 return false; 94 result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( 95 fs_name, 96 storage::kFileSystemTypeItunes, 97 storage::FileSystemMountOption(), 98 root.AppendASCII("itunes")); 99 if (!result) 100 return result; 101 102 itunes_fs_names_.insert(fs_name); 103 104 if (itunes_fs_names_.size() == 1) { 105 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 106 FROM_HERE, 107 Bind(&ImportedMediaGalleryRegistry::RegisterITunesFileSystem, 108 base::Unretained(this), library_xml_path)); 109 #ifndef NDEBUG 110 itunes_xml_library_path_ = library_xml_path; 111 } else { 112 DCHECK_EQ(itunes_xml_library_path_.value(), library_xml_path.value()); 113 #endif 114 } 115 #endif // defined(OS_WIN) || defined(OS_MACOSX) 116 117 return result; 118 } 119 120 bool ImportedMediaGalleryRegistry::RegisterIPhotoFilesystemOnUIThread( 121 const std::string& fs_name, const base::FilePath& library_xml_path) { 122 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 123 DCHECK(!library_xml_path.empty()); 124 125 bool result = false; 126 127 // TODO(gbillock): Investigate how to refactor this to reduce duplicated 128 // code. 129 #if defined(OS_MACOSX) 130 base::FilePath root = ImportedRoot(); 131 if (root.empty()) 132 return false; 133 result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( 134 fs_name, 135 storage::kFileSystemTypeIphoto, 136 storage::FileSystemMountOption(), 137 root.AppendASCII("iphoto")); 138 if (!result) 139 return result; 140 141 iphoto_fs_names_.insert(fs_name); 142 143 if (iphoto_fs_names_.size() == 1) { 144 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 145 FROM_HERE, 146 Bind(&ImportedMediaGalleryRegistry::RegisterIPhotoFileSystem, 147 base::Unretained(this), library_xml_path)); 148 #ifndef NDEBUG 149 iphoto_xml_library_path_ = library_xml_path; 150 } else { 151 DCHECK_EQ(iphoto_xml_library_path_.value(), library_xml_path.value()); 152 #endif 153 } 154 #endif // defined(OS_MACOSX) 155 156 return result; 157 } 158 159 bool ImportedMediaGalleryRegistry::RevokeImportedFilesystemOnUIThread( 160 const std::string& fs_name) { 161 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 162 163 #if defined(OS_WIN) || defined(OS_MACOSX) 164 if (picasa_fs_names_.erase(fs_name)) { 165 if (picasa_fs_names_.empty()) { 166 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 167 FROM_HERE, 168 Bind(&ImportedMediaGalleryRegistry::RevokePicasaFileSystem, 169 base::Unretained(this))); 170 } 171 return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); 172 } 173 174 if (itunes_fs_names_.erase(fs_name)) { 175 if (itunes_fs_names_.empty()) { 176 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 177 FROM_HERE, 178 Bind(&ImportedMediaGalleryRegistry::RevokeITunesFileSystem, 179 base::Unretained(this))); 180 } 181 return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); 182 } 183 #endif // defined(OS_WIN) || defined(OS_MACOSX) 184 185 #if defined(OS_MACOSX) 186 if (iphoto_fs_names_.erase(fs_name)) { 187 if (iphoto_fs_names_.empty()) { 188 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 189 FROM_HERE, 190 Bind(&ImportedMediaGalleryRegistry::RevokeIPhotoFileSystem, 191 base::Unretained(this))); 192 } 193 return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); 194 } 195 #endif // defined(OS_MACOSX) 196 197 return false; 198 } 199 200 base::FilePath ImportedMediaGalleryRegistry::ImportedRoot() { 201 DCHECK(!imported_root_.empty()); 202 return imported_root_; 203 } 204 205 #if defined(OS_WIN) || defined(OS_MACOSX) 206 // static 207 picasa::PicasaDataProvider* 208 ImportedMediaGalleryRegistry::PicasaDataProvider() { 209 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 210 DCHECK(GetInstance()->picasa_data_provider_); 211 return GetInstance()->picasa_data_provider_.get(); 212 } 213 214 // static 215 itunes::ITunesDataProvider* 216 ImportedMediaGalleryRegistry::ITunesDataProvider() { 217 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 218 DCHECK(GetInstance()->itunes_data_provider_); 219 return GetInstance()->itunes_data_provider_.get(); 220 } 221 #endif // defined(OS_WIN) || defined(OS_MACOSX) 222 223 #if defined(OS_MACOSX) 224 // static 225 iphoto::IPhotoDataProvider* 226 ImportedMediaGalleryRegistry::IPhotoDataProvider() { 227 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 228 DCHECK(GetInstance()->iphoto_data_provider_); 229 return GetInstance()->iphoto_data_provider_.get(); 230 } 231 #endif // defined(OS_MACOSX) 232 233 ImportedMediaGalleryRegistry::ImportedMediaGalleryRegistry() {} 234 235 ImportedMediaGalleryRegistry::~ImportedMediaGalleryRegistry() { 236 if (!imported_root_.empty()) 237 base::DeleteFile(imported_root_, false); 238 #if defined(OS_WIN) || defined(OS_MACOSX) 239 DCHECK_EQ(0U, picasa_fs_names_.size()); 240 DCHECK_EQ(0U, itunes_fs_names_.size()); 241 #endif // defined(OS_WIN) || defined(OS_MACOSX) 242 #if defined(OS_MACOSX) 243 DCHECK_EQ(0U, iphoto_fs_names_.size()); 244 #endif // defined(OS_MACOSX) 245 } 246 247 #if defined(OS_WIN) || defined(OS_MACOSX) 248 void ImportedMediaGalleryRegistry::RegisterPicasaFileSystem( 249 const base::FilePath& database_path) { 250 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 251 DCHECK(!picasa_data_provider_); 252 picasa_data_provider_.reset(new picasa::PicasaDataProvider(database_path)); 253 } 254 255 void ImportedMediaGalleryRegistry::RevokePicasaFileSystem() { 256 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 257 DCHECK(picasa_data_provider_); 258 picasa_data_provider_.reset(); 259 } 260 261 void ImportedMediaGalleryRegistry::RegisterITunesFileSystem( 262 const base::FilePath& xml_library_path) { 263 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 264 DCHECK(!itunes_data_provider_); 265 itunes_data_provider_.reset(new itunes::ITunesDataProvider(xml_library_path)); 266 } 267 268 void ImportedMediaGalleryRegistry::RevokeITunesFileSystem() { 269 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 270 DCHECK(itunes_data_provider_); 271 itunes_data_provider_.reset(); 272 } 273 #endif // defined(OS_WIN) || defined(OS_MACOSX) 274 275 #if defined(OS_MACOSX) 276 void ImportedMediaGalleryRegistry::RegisterIPhotoFileSystem( 277 const base::FilePath& xml_library_path) { 278 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 279 DCHECK(!iphoto_data_provider_); 280 iphoto_data_provider_.reset(new iphoto::IPhotoDataProvider(xml_library_path)); 281 } 282 283 void ImportedMediaGalleryRegistry::RevokeIPhotoFileSystem() { 284 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 285 DCHECK(iphoto_data_provider_); 286 iphoto_data_provider_.reset(); 287 } 288 #endif // defined(OS_MACOSX) 289