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/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 "webkit/browser/fileapi/external_mount_points.h" 17 #include "webkit/common/fileapi/file_system_mount_option.h" 18 19 using base::Bind; 20 using fileapi::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, fileapi::kFileSystemTypePicasa, fileapi::FileSystemMountOption(), 59 root.AppendASCII("picasa")); 60 if (!result) 61 return result; 62 63 picasa_fs_names_.insert(fs_name); 64 65 if (picasa_fs_names_.size() == 1) { 66 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 67 FROM_HERE, 68 Bind(&ImportedMediaGalleryRegistry::RegisterPicasaFileSystem, 69 base::Unretained(this), database_path)); 70 #ifndef NDEBUG 71 picasa_database_path_ = database_path; 72 } else { 73 DCHECK_EQ(picasa_database_path_.value(), database_path.value()); 74 #endif 75 } 76 #endif // defined(OS_WIN) || defined(OS_MACOSX) 77 78 return result; 79 } 80 81 bool ImportedMediaGalleryRegistry::RegisterITunesFilesystemOnUIThread( 82 const std::string& fs_name, const base::FilePath& library_xml_path) { 83 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 84 DCHECK(!library_xml_path.empty()); 85 86 bool result = false; 87 88 #if defined(OS_WIN) || defined(OS_MACOSX) 89 base::FilePath root = ImportedRoot(); 90 if (root.empty()) 91 return false; 92 result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( 93 fs_name, fileapi::kFileSystemTypeItunes, fileapi::FileSystemMountOption(), 94 root.AppendASCII("itunes")); 95 if (!result) 96 return result; 97 98 itunes_fs_names_.insert(fs_name); 99 100 if (itunes_fs_names_.size() == 1) { 101 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 102 FROM_HERE, 103 Bind(&ImportedMediaGalleryRegistry::RegisterITunesFileSystem, 104 base::Unretained(this), library_xml_path)); 105 #ifndef NDEBUG 106 itunes_xml_library_path_ = library_xml_path; 107 } else { 108 DCHECK_EQ(itunes_xml_library_path_.value(), library_xml_path.value()); 109 #endif 110 } 111 #endif // defined(OS_WIN) || defined(OS_MACOSX) 112 113 return result; 114 } 115 116 bool ImportedMediaGalleryRegistry::RegisterIPhotoFilesystemOnUIThread( 117 const std::string& fs_name, const base::FilePath& library_xml_path) { 118 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 119 DCHECK(!library_xml_path.empty()); 120 121 bool result = false; 122 123 // TODO(gbillock): Investigate how to refactor this to reduce duplicated 124 // code. 125 #if defined(OS_MACOSX) 126 base::FilePath root = ImportedRoot(); 127 if (root.empty()) 128 return false; 129 result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( 130 fs_name, fileapi::kFileSystemTypeIphoto, fileapi::FileSystemMountOption(), 131 root.AppendASCII("iphoto")); 132 if (!result) 133 return result; 134 135 iphoto_fs_names_.insert(fs_name); 136 137 if (iphoto_fs_names_.size() == 1) { 138 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 139 FROM_HERE, 140 Bind(&ImportedMediaGalleryRegistry::RegisterIPhotoFileSystem, 141 base::Unretained(this), library_xml_path)); 142 #ifndef NDEBUG 143 iphoto_xml_library_path_ = library_xml_path; 144 } else { 145 DCHECK_EQ(iphoto_xml_library_path_.value(), library_xml_path.value()); 146 #endif 147 } 148 #endif // defined(OS_MACOSX) 149 150 return result; 151 } 152 153 bool ImportedMediaGalleryRegistry::RevokeImportedFilesystemOnUIThread( 154 const std::string& fs_name) { 155 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 156 157 #if defined(OS_WIN) || defined(OS_MACOSX) 158 if (picasa_fs_names_.erase(fs_name)) { 159 if (picasa_fs_names_.empty()) { 160 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 161 FROM_HERE, 162 Bind(&ImportedMediaGalleryRegistry::RevokePicasaFileSystem, 163 base::Unretained(this))); 164 } 165 return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); 166 } 167 168 if (itunes_fs_names_.erase(fs_name)) { 169 if (itunes_fs_names_.empty()) { 170 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 171 FROM_HERE, 172 Bind(&ImportedMediaGalleryRegistry::RevokeITunesFileSystem, 173 base::Unretained(this))); 174 } 175 return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); 176 } 177 #endif // defined(OS_WIN) || defined(OS_MACOSX) 178 179 #if defined(OS_MACOSX) 180 if (iphoto_fs_names_.erase(fs_name)) { 181 if (iphoto_fs_names_.empty()) { 182 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 183 FROM_HERE, 184 Bind(&ImportedMediaGalleryRegistry::RevokeIPhotoFileSystem, 185 base::Unretained(this))); 186 } 187 return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); 188 } 189 #endif // defined(OS_MACOSX) 190 191 return false; 192 } 193 194 base::FilePath ImportedMediaGalleryRegistry::ImportedRoot() { 195 DCHECK(!imported_root_.empty()); 196 return imported_root_; 197 } 198 199 #if defined(OS_WIN) || defined(OS_MACOSX) 200 // static 201 picasa::PicasaDataProvider* 202 ImportedMediaGalleryRegistry::PicasaDataProvider() { 203 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 204 DCHECK(GetInstance()->picasa_data_provider_); 205 return GetInstance()->picasa_data_provider_.get(); 206 } 207 208 // static 209 itunes::ITunesDataProvider* 210 ImportedMediaGalleryRegistry::ITunesDataProvider() { 211 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 212 DCHECK(GetInstance()->itunes_data_provider_); 213 return GetInstance()->itunes_data_provider_.get(); 214 } 215 #endif // defined(OS_WIN) || defined(OS_MACOSX) 216 217 #if defined(OS_MACOSX) 218 // static 219 iphoto::IPhotoDataProvider* 220 ImportedMediaGalleryRegistry::IPhotoDataProvider() { 221 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 222 DCHECK(GetInstance()->iphoto_data_provider_); 223 return GetInstance()->iphoto_data_provider_.get(); 224 } 225 #endif // defined(OS_MACOSX) 226 227 ImportedMediaGalleryRegistry::ImportedMediaGalleryRegistry() {} 228 229 ImportedMediaGalleryRegistry::~ImportedMediaGalleryRegistry() { 230 if (!imported_root_.empty()) 231 base::DeleteFile(imported_root_, false); 232 #if defined(OS_WIN) || defined(OS_MACOSX) 233 DCHECK_EQ(0U, picasa_fs_names_.size()); 234 DCHECK_EQ(0U, itunes_fs_names_.size()); 235 #endif // defined(OS_WIN) || defined(OS_MACOSX) 236 #if defined(OS_MACOSX) 237 DCHECK_EQ(0U, iphoto_fs_names_.size()); 238 #endif // defined(OS_MACOSX) 239 } 240 241 #if defined(OS_WIN) || defined(OS_MACOSX) 242 void ImportedMediaGalleryRegistry::RegisterPicasaFileSystem( 243 const base::FilePath& database_path) { 244 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 245 DCHECK(!picasa_data_provider_); 246 picasa_data_provider_.reset(new picasa::PicasaDataProvider(database_path)); 247 } 248 249 void ImportedMediaGalleryRegistry::RevokePicasaFileSystem() { 250 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 251 DCHECK(picasa_data_provider_); 252 picasa_data_provider_.reset(); 253 } 254 255 void ImportedMediaGalleryRegistry::RegisterITunesFileSystem( 256 const base::FilePath& xml_library_path) { 257 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 258 DCHECK(!itunes_data_provider_); 259 itunes_data_provider_.reset(new itunes::ITunesDataProvider(xml_library_path)); 260 } 261 262 void ImportedMediaGalleryRegistry::RevokeITunesFileSystem() { 263 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 264 DCHECK(itunes_data_provider_); 265 itunes_data_provider_.reset(); 266 } 267 #endif // defined(OS_WIN) || defined(OS_MACOSX) 268 269 #if defined(OS_MACOSX) 270 void ImportedMediaGalleryRegistry::RegisterIPhotoFileSystem( 271 const base::FilePath& xml_library_path) { 272 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 273 DCHECK(!iphoto_data_provider_); 274 iphoto_data_provider_.reset(new iphoto::IPhotoDataProvider(xml_library_path)); 275 } 276 277 void ImportedMediaGalleryRegistry::RevokeIPhotoFileSystem() { 278 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 279 DCHECK(iphoto_data_provider_); 280 iphoto_data_provider_.reset(); 281 } 282 #endif // defined(OS_MACOSX) 283