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 19using base::Bind; 20using storage::ExternalMountPoints; 21 22namespace { 23 24static base::LazyInstance<ImportedMediaGalleryRegistry>::Leaky 25g_imported_media_gallery_registry = LAZY_INSTANCE_INITIALIZER; 26 27} // namespace 28 29// static 30ImportedMediaGalleryRegistry* ImportedMediaGalleryRegistry::GetInstance() { 31 return g_imported_media_gallery_registry.Pointer(); 32} 33 34void 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 45bool 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 83bool 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 120bool 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 159bool 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 200base::FilePath ImportedMediaGalleryRegistry::ImportedRoot() { 201 DCHECK(!imported_root_.empty()); 202 return imported_root_; 203} 204 205#if defined(OS_WIN) || defined(OS_MACOSX) 206// static 207picasa::PicasaDataProvider* 208ImportedMediaGalleryRegistry::PicasaDataProvider() { 209 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 210 DCHECK(GetInstance()->picasa_data_provider_); 211 return GetInstance()->picasa_data_provider_.get(); 212} 213 214// static 215itunes::ITunesDataProvider* 216ImportedMediaGalleryRegistry::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 225iphoto::IPhotoDataProvider* 226ImportedMediaGalleryRegistry::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 233ImportedMediaGalleryRegistry::ImportedMediaGalleryRegistry() {} 234 235ImportedMediaGalleryRegistry::~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) 248void 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 255void ImportedMediaGalleryRegistry::RevokePicasaFileSystem() { 256 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 257 DCHECK(picasa_data_provider_); 258 picasa_data_provider_.reset(); 259} 260 261void 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 268void 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) 276void 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 283void ImportedMediaGalleryRegistry::RevokeIPhotoFileSystem() { 284 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 285 DCHECK(iphoto_data_provider_); 286 iphoto_data_provider_.reset(); 287} 288#endif // defined(OS_MACOSX) 289