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.
5 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h"
10 #include "base/callback.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/threading/thread_restrictions.h"
16 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
17 #include "chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.h"
21 IPhotoDataProvider::IPhotoDataProvider(const base::FilePath
& library_path
)
22 : iapps::IAppsDataProvider(library_path
),
23 weak_factory_(this) {}
25 IPhotoDataProvider::~IPhotoDataProvider() {}
27 void IPhotoDataProvider::DoParseLibrary(
28 const base::FilePath
& library_path
,
29 const ReadyCallback
& ready_callback
) {
30 xml_parser_
= new iapps::SafeIAppsLibraryParser
;
31 xml_parser_
->ParseIPhotoLibrary(
33 base::Bind(&IPhotoDataProvider::OnLibraryParsed
,
34 weak_factory_
.GetWeakPtr(),
38 void IPhotoDataProvider::OnLibraryParsed(const ReadyCallback
& ready_callback
,
40 const parser::Library
& library
) {
41 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
44 BuildIndices(library
);
45 ready_callback
.Run(valid());
48 void IPhotoDataProvider::BuildIndices(const parser::Library
& library
) {
49 typedef base::hash_map
<uint64
, const base::FilePath
*> IdIndex
;
51 IdIndex photo_id_index
;
52 IdIndex originals_id_index
;
53 for (std::set
<parser::Photo
>::const_iterator photo_it
=
54 library
.all_photos
.begin();
55 photo_it
!= library
.all_photos
.end(); photo_it
++) {
56 photo_id_index
[photo_it
->id
] = &(photo_it
->location
);
57 if (!photo_it
->original_location
.empty())
58 originals_id_index
[photo_it
->id
] = &(photo_it
->original_location
);
61 // Build up a set of IDs which have in-album duplicates.
62 // Those are the filenames we want to globally mangle.
63 std::set
<uint64
> dupe_ids
;
64 for (parser::Albums::const_iterator album_it
= library
.albums
.begin();
65 album_it
!= library
.albums
.end(); album_it
++) {
66 const parser::Album
& album
= album_it
->second
;
68 std::set
<std::string
> album_paths
;
69 for (parser::Album::const_iterator id_it
= album
.begin();
70 id_it
!= album
.end(); id_it
++) {
72 IdIndex::const_iterator photo_it
= photo_id_index
.find(id
);
73 if (photo_it
== photo_id_index
.end())
76 std::string filename
= photo_it
->second
->BaseName().value();
77 if (ContainsKey(album_paths
, filename
))
80 album_paths
.insert(filename
);
84 // Now build the directory index.
86 originals_index_
.clear();
87 for (parser::Albums::const_iterator album_it
= library
.albums
.begin();
88 album_it
!= library
.albums
.end(); album_it
++) {
89 std::string album_name
= album_it
->first
;
90 const parser::Album
& album
= album_it
->second
;
92 for (parser::Album::const_iterator id_it
= album
.begin();
93 id_it
!= album
.end(); id_it
++) {
95 IdIndex::const_iterator photo_it
= photo_id_index
.find(id
);
96 if (photo_it
== photo_id_index
.end())
98 base::FilePath path
= *(photo_it
->second
);
100 std::string filename
= path
.BaseName().value();
101 if (ContainsKey(dupe_ids
, id
)) {
102 filename
= path
.BaseName().InsertBeforeExtension(
103 "(" + base::Uint64ToString(id
) + ")").value();
106 dir_index_
[album_name
][filename
] = path
;
108 IdIndex::const_iterator original_it
= originals_id_index
.find(id
);
109 if (original_it
!= originals_id_index
.end())
110 originals_index_
[album_name
][filename
] = *(original_it
->second
);
115 std::vector
<std::string
> IPhotoDataProvider::GetAlbumNames() const {
116 std::vector
<std::string
> names
;
118 for (DirIndex::const_iterator dir_it
= dir_index_
.begin();
119 dir_it
!= dir_index_
.end(); dir_it
++) {
120 names
.push_back(dir_it
->first
);
126 std::map
<std::string
, base::FilePath
> IPhotoDataProvider::GetAlbumContents(
127 const std::string
& album
) const {
128 std::map
<std::string
, base::FilePath
> locations
;
129 DirIndex::const_iterator dir_it
= dir_index_
.find(album
);
130 if (dir_it
== dir_index_
.end())
133 for (FileIndex::const_iterator file_it
= dir_it
->second
.begin();
134 file_it
!= dir_it
->second
.end(); file_it
++) {
135 locations
.insert(make_pair(file_it
->first
, file_it
->second
));
141 base::FilePath
IPhotoDataProvider::GetPhotoLocationInAlbum(
142 const std::string
& album
,
143 const std::string
& filename
) const {
144 DirIndex::const_iterator dir_it
= dir_index_
.find(album
);
145 if (dir_it
== dir_index_
.end())
146 return base::FilePath();
147 FileIndex::const_iterator file_it
= dir_it
->second
.find(filename
);
148 if (file_it
== dir_it
->second
.end())
149 return base::FilePath();
150 return file_it
->second
;
153 bool IPhotoDataProvider::HasOriginals(const std::string
& album
) const {
154 DirIndex::const_iterator originals_it
= originals_index_
.find(album
);
155 return originals_it
!= originals_index_
.end();
158 std::map
<std::string
, base::FilePath
> IPhotoDataProvider::GetOriginals(
159 const std::string
& album
) const {
160 std::map
<std::string
, base::FilePath
> locations
;
161 DirIndex::const_iterator originals_it
= originals_index_
.find(album
);
162 if (originals_it
== originals_index_
.end())
165 for (FileIndex::const_iterator file_it
= originals_it
->second
.begin();
166 file_it
!= originals_it
->second
.end(); file_it
++) {
167 locations
.insert(make_pair(file_it
->first
, file_it
->second
));
173 base::FilePath
IPhotoDataProvider::GetOriginalPhotoLocation(
174 const std::string
& album
,
175 const std::string
& filename
) const {
176 DirIndex::const_iterator originals_it
= originals_index_
.find(album
);
177 if (originals_it
== originals_index_
.end())
178 return base::FilePath();
179 FileIndex::const_iterator file_it
= originals_it
->second
.find(filename
);
180 if (file_it
== originals_it
->second
.end())
181 return base::FilePath();
182 return file_it
->second
;
185 } // namespace iphoto