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
GetInstance()30 ImportedMediaGalleryRegistry* ImportedMediaGalleryRegistry::GetInstance() {
31 return g_imported_media_gallery_registry.Pointer();
32 }
33
Initialize()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
RegisterPicasaFilesystemOnUIThread(const std::string & fs_name,const base::FilePath & database_path)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
RegisterITunesFilesystemOnUIThread(const std::string & fs_name,const base::FilePath & library_xml_path)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
RegisterIPhotoFilesystemOnUIThread(const std::string & fs_name,const base::FilePath & library_xml_path)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
RevokeImportedFilesystemOnUIThread(const std::string & fs_name)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
ImportedRoot()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*
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*
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*
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
ImportedMediaGalleryRegistry()227 ImportedMediaGalleryRegistry::ImportedMediaGalleryRegistry() {}
228
~ImportedMediaGalleryRegistry()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)
RegisterPicasaFileSystem(const base::FilePath & database_path)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
RevokePicasaFileSystem()249 void ImportedMediaGalleryRegistry::RevokePicasaFileSystem() {
250 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
251 DCHECK(picasa_data_provider_);
252 picasa_data_provider_.reset();
253 }
254
RegisterITunesFileSystem(const base::FilePath & xml_library_path)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
RevokeITunesFileSystem()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)
RegisterIPhotoFileSystem(const base::FilePath & xml_library_path)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
RevokeIPhotoFileSystem()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