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/platform_file.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
18 #include "chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.h"
22 IPhotoDataProvider::IPhotoDataProvider(const base::FilePath
& library_path
)
23 : iapps::IAppsDataProvider(library_path
),
24 weak_factory_(this) {}
26 IPhotoDataProvider::~IPhotoDataProvider() {}
28 void IPhotoDataProvider::DoParseLibrary(
29 const base::FilePath
& library_path
,
30 const ReadyCallback
& ready_callback
) {
31 xml_parser_
= new iapps::SafeIAppsLibraryParser
;
32 xml_parser_
->ParseIPhotoLibrary(
34 base::Bind(&IPhotoDataProvider::OnLibraryParsed
,
35 weak_factory_
.GetWeakPtr(),
39 void IPhotoDataProvider::OnLibraryParsed(const ReadyCallback
& ready_callback
,
41 const parser::Library
& library
) {
42 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
45 BuildIndices(library
);
46 ready_callback
.Run(valid());
49 void IPhotoDataProvider::BuildIndices(const parser::Library
& library
) {
50 typedef base::hash_map
<uint64
, const base::FilePath
*> IdIndex
;
51 typedef base::hash_map
<uint64
, std::string
> IdFileNameIndex
;
53 IdIndex photo_id_index
;
54 IdIndex originals_id_index
;
55 for (std::set
<parser::Photo
>::const_iterator photo_it
=
56 library
.all_photos
.begin();
57 photo_it
!= library
.all_photos
.end(); photo_it
++) {
58 photo_id_index
[photo_it
->id
] = &(photo_it
->location
);
59 if (!photo_it
->original_location
.empty())
60 originals_id_index
[photo_it
->id
] = &(photo_it
->original_location
);
63 // Build up a set of IDs which have in-album duplicates.
64 // Those are the filenames we want to globally mangle.
65 std::set
<uint64
> dupe_ids
;
66 for (parser::Albums::const_iterator album_it
= library
.albums
.begin();
67 album_it
!= library
.albums
.end(); album_it
++) {
68 const parser::Album
& album
= album_it
->second
;
70 std::set
<std::string
> album_paths
;
71 for (parser::Album::const_iterator id_it
= album
.begin();
72 id_it
!= album
.end(); id_it
++) {
74 IdIndex::const_iterator photo_it
= photo_id_index
.find(id
);
75 if (photo_it
== photo_id_index
.end())
78 std::string filename
= photo_it
->second
->BaseName().value();
79 if (ContainsKey(album_paths
, filename
))
82 album_paths
.insert(filename
);
86 // Now build the directory index.
88 originals_index_
.clear();
89 for (parser::Albums::const_iterator album_it
= library
.albums
.begin();
90 album_it
!= library
.albums
.end(); album_it
++) {
91 std::string album_name
= album_it
->first
;
92 const parser::Album
& album
= album_it
->second
;
94 for (parser::Album::const_iterator id_it
= album
.begin();
95 id_it
!= album
.end(); id_it
++) {
97 IdIndex::const_iterator photo_it
= photo_id_index
.find(id
);
98 if (photo_it
== photo_id_index
.end())
100 base::FilePath path
= *(photo_it
->second
);
102 std::string filename
= path
.BaseName().value();
103 if (ContainsKey(dupe_ids
, id
)) {
104 filename
= path
.BaseName().InsertBeforeExtension(
105 "(" + base::Uint64ToString(id
) + ")").value();
108 dir_index_
[album_name
][filename
] = path
;
110 IdIndex::const_iterator original_it
= originals_id_index
.find(id
);
111 if (original_it
!= originals_id_index
.end())
112 originals_index_
[album_name
][filename
] = *(original_it
->second
);
117 std::vector
<std::string
> IPhotoDataProvider::GetAlbumNames() const {
118 std::vector
<std::string
> names
;
120 for (DirIndex::const_iterator dir_it
= dir_index_
.begin();
121 dir_it
!= dir_index_
.end(); dir_it
++) {
122 names
.push_back(dir_it
->first
);
128 std::map
<std::string
, base::FilePath
> IPhotoDataProvider::GetAlbumContents(
129 const std::string
& album
) const {
130 std::map
<std::string
, base::FilePath
> locations
;
131 DirIndex::const_iterator dir_it
= dir_index_
.find(album
);
132 if (dir_it
== dir_index_
.end())
135 for (FileIndex::const_iterator file_it
= dir_it
->second
.begin();
136 file_it
!= dir_it
->second
.end(); file_it
++) {
137 locations
.insert(make_pair(file_it
->first
, file_it
->second
));
143 base::FilePath
IPhotoDataProvider::GetPhotoLocationInAlbum(
144 const std::string
& album
,
145 const std::string
& filename
) const {
146 DirIndex::const_iterator dir_it
= dir_index_
.find(album
);
147 if (dir_it
== dir_index_
.end())
148 return base::FilePath();
149 FileIndex::const_iterator file_it
= dir_it
->second
.find(filename
);
150 if (file_it
== dir_it
->second
.end())
151 return base::FilePath();
152 return file_it
->second
;
155 bool IPhotoDataProvider::HasOriginals(const std::string
& album
) const {
156 DirIndex::const_iterator originals_it
= originals_index_
.find(album
);
157 return originals_it
!= originals_index_
.end();
160 std::map
<std::string
, base::FilePath
> IPhotoDataProvider::GetOriginals(
161 const std::string
& album
) const {
162 std::map
<std::string
, base::FilePath
> locations
;
163 DirIndex::const_iterator originals_it
= originals_index_
.find(album
);
164 if (originals_it
== originals_index_
.end())
167 for (FileIndex::const_iterator file_it
= originals_it
->second
.begin();
168 file_it
!= originals_it
->second
.end(); file_it
++) {
169 locations
.insert(make_pair(file_it
->first
, file_it
->second
));
175 base::FilePath
IPhotoDataProvider::GetOriginalPhotoLocation(
176 const std::string
& album
,
177 const std::string
& filename
) const {
178 DirIndex::const_iterator originals_it
= originals_index_
.find(album
);
179 if (originals_it
== originals_index_
.end())
180 return base::FilePath();
181 FileIndex::const_iterator file_it
= originals_it
->second
.find(filename
);
182 if (file_it
== originals_it
->second
.end())
183 return base::FilePath();
184 return file_it
->second
;
187 } // namespace iphoto