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"
19 #include "content/public/browser/browser_thread.h"
23 IPhotoDataProvider::IPhotoDataProvider(const base::FilePath
& library_path
)
24 : iapps::IAppsDataProvider(library_path
),
25 weak_factory_(this) {}
27 IPhotoDataProvider::~IPhotoDataProvider() {}
29 void IPhotoDataProvider::DoParseLibrary(
30 const base::FilePath
& library_path
,
31 const ReadyCallback
& ready_callback
) {
32 xml_parser_
= new iapps::SafeIAppsLibraryParser
;
33 xml_parser_
->ParseIPhotoLibrary(
35 base::Bind(&IPhotoDataProvider::OnLibraryParsed
,
36 weak_factory_
.GetWeakPtr(),
40 void IPhotoDataProvider::OnLibraryParsed(const ReadyCallback
& ready_callback
,
42 const parser::Library
& library
) {
43 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
46 BuildIndices(library
);
47 ready_callback
.Run(valid());
50 void IPhotoDataProvider::BuildIndices(const parser::Library
& library
) {
51 typedef base::hash_map
<uint64
, const base::FilePath
*> IdIndex
;
52 typedef base::hash_map
<uint64
, std::string
> IdFileNameIndex
;
54 IdIndex photo_id_index
;
55 IdIndex originals_id_index
;
56 for (std::set
<parser::Photo
>::const_iterator photo_it
=
57 library
.all_photos
.begin();
58 photo_it
!= library
.all_photos
.end(); photo_it
++) {
59 photo_id_index
[photo_it
->id
] = &(photo_it
->location
);
60 if (!photo_it
->original_location
.empty())
61 originals_id_index
[photo_it
->id
] = &(photo_it
->original_location
);
64 // Build up a set of IDs which have in-album duplicates.
65 // Those are the filenames we want to globally mangle.
66 std::set
<uint64
> dupe_ids
;
67 for (parser::Albums::const_iterator album_it
= library
.albums
.begin();
68 album_it
!= library
.albums
.end(); album_it
++) {
69 const parser::Album
& album
= album_it
->second
;
71 std::set
<std::string
> album_paths
;
72 for (parser::Album::const_iterator id_it
= album
.begin();
73 id_it
!= album
.end(); id_it
++) {
75 IdIndex::const_iterator photo_it
= photo_id_index
.find(id
);
76 if (photo_it
== photo_id_index
.end())
79 std::string filename
= photo_it
->second
->BaseName().value();
80 if (ContainsKey(album_paths
, filename
))
83 album_paths
.insert(filename
);
87 // Now build the directory index.
89 originals_index_
.clear();
90 for (parser::Albums::const_iterator album_it
= library
.albums
.begin();
91 album_it
!= library
.albums
.end(); album_it
++) {
92 std::string album_name
= album_it
->first
;
93 const parser::Album
& album
= album_it
->second
;
95 for (parser::Album::const_iterator id_it
= album
.begin();
96 id_it
!= album
.end(); id_it
++) {
98 IdIndex::const_iterator photo_it
= photo_id_index
.find(id
);
99 if (photo_it
== photo_id_index
.end())
101 base::FilePath path
= *(photo_it
->second
);
103 std::string filename
= path
.BaseName().value();
104 if (ContainsKey(dupe_ids
, id
)) {
105 filename
= path
.BaseName().InsertBeforeExtension(
106 "(" + base::Uint64ToString(id
) + ")").value();
109 dir_index_
[album_name
][filename
] = path
;
111 IdIndex::const_iterator original_it
= originals_id_index
.find(id
);
112 if (original_it
!= originals_id_index
.end())
113 originals_index_
[album_name
][filename
] = *(original_it
->second
);
118 std::vector
<std::string
> IPhotoDataProvider::GetAlbumNames() const {
119 std::vector
<std::string
> names
;
121 for (DirIndex::const_iterator dir_it
= dir_index_
.begin();
122 dir_it
!= dir_index_
.end(); dir_it
++) {
123 names
.push_back(dir_it
->first
);
129 std::map
<std::string
, base::FilePath
> IPhotoDataProvider::GetAlbumContents(
130 const std::string
& album
) const {
131 std::map
<std::string
, base::FilePath
> locations
;
132 DirIndex::const_iterator dir_it
= dir_index_
.find(album
);
133 if (dir_it
== dir_index_
.end())
136 for (FileIndex::const_iterator file_it
= dir_it
->second
.begin();
137 file_it
!= dir_it
->second
.end(); file_it
++) {
138 locations
.insert(make_pair(file_it
->first
, file_it
->second
));
144 base::FilePath
IPhotoDataProvider::GetPhotoLocationInAlbum(
145 const std::string
& album
,
146 const std::string
& filename
) const {
147 DirIndex::const_iterator dir_it
= dir_index_
.find(album
);
148 if (dir_it
== dir_index_
.end())
149 return base::FilePath();
150 FileIndex::const_iterator file_it
= dir_it
->second
.find(filename
);
151 if (file_it
== dir_it
->second
.end())
152 return base::FilePath();
153 return file_it
->second
;
156 bool IPhotoDataProvider::HasOriginals(const std::string
& album
) const {
157 DirIndex::const_iterator originals_it
= originals_index_
.find(album
);
158 return originals_it
!= originals_index_
.end();
161 std::map
<std::string
, base::FilePath
> IPhotoDataProvider::GetOriginals(
162 const std::string
& album
) const {
163 std::map
<std::string
, base::FilePath
> locations
;
164 DirIndex::const_iterator originals_it
= originals_index_
.find(album
);
165 if (originals_it
== originals_index_
.end())
168 for (FileIndex::const_iterator file_it
= originals_it
->second
.begin();
169 file_it
!= originals_it
->second
.end(); file_it
++) {
170 locations
.insert(make_pair(file_it
->first
, file_it
->second
));
176 base::FilePath
IPhotoDataProvider::GetOriginalPhotoLocation(
177 const std::string
& album
,
178 const std::string
& filename
) const {
179 DirIndex::const_iterator originals_it
= originals_index_
.find(album
);
180 if (originals_it
== originals_index_
.end())
181 return base::FilePath();
182 FileIndex::const_iterator file_it
= originals_it
->second
.find(filename
);
183 if (file_it
== originals_it
->second
.end())
184 return base::FilePath();
185 return file_it
->second
;
188 } // namespace iphoto