| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/utility/media_galleries/iphoto_library_parser.h" | 5 #include "chrome/utility/media_galleries/iphoto_library_parser.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 13 #include "chrome/utility/media_galleries/iapps_xml_utils.h" | 13 #include "chrome/utility/media_galleries/iapps_xml_utils.h" |
| 14 #include "third_party/libxml/chromium/libxml_utils.h" | 14 #include "third_party/libxml/chromium/libxml_utils.h" |
| 15 | 15 |
| 16 namespace iphoto { | 16 namespace iphoto { |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 struct PhotoInfo { | 20 struct PhotoInfo { |
| 21 uint64 id; | 21 uint64 id; |
| 22 std::string guid; | |
| 23 base::FilePath location; | 22 base::FilePath location; |
| 24 std::string type; | 23 base::FilePath original_location; |
| 25 }; | 24 }; |
| 26 | 25 |
| 27 struct AlbumInfo { | 26 struct AlbumInfo { |
| 28 std::set<uint64> photo_ids; | 27 std::set<uint64> photo_ids; |
| 29 std::string name; | 28 std::string name; |
| 30 uint64 id; | 29 uint64 id; |
| 31 }; | 30 }; |
| 32 | 31 |
| 33 // Walk through a dictionary filling in |result| with photo information. Return | 32 // Walk through a dictionary filling in |result| with photo information. Return |
| 34 // true if at least the id and location were found. | 33 // true if at least the id and location were found. |
| 35 // In either case, the cursor is advanced out of the dictionary. | 34 // In either case, the cursor is advanced out of the dictionary. |
| 36 bool GetPhotoInfoFromDict(XmlReader* reader, PhotoInfo* result) { | 35 bool GetPhotoInfoFromDict(XmlReader* reader, PhotoInfo* result) { |
| 37 DCHECK(result); | 36 DCHECK(result); |
| 38 if (reader->NodeName() != "dict") | 37 if (reader->NodeName() != "dict") |
| 39 return false; | 38 return false; |
| 40 | 39 |
| 41 int dict_content_depth = reader->Depth() + 1; | 40 int dict_content_depth = reader->Depth() + 1; |
| 42 // Advance past the dict node and into the body of the dictionary. | 41 // Advance past the dict node and into the body of the dictionary. |
| 43 if (!reader->Read()) | 42 if (!reader->Read()) |
| 44 return false; | 43 return false; |
| 45 | 44 |
| 46 bool found_guid = false; | |
| 47 bool found_location = false; | 45 bool found_location = false; |
| 48 bool found_type = false; | 46 while (reader->Depth() >= dict_content_depth) { |
| 49 while (reader->Depth() >= dict_content_depth && | |
| 50 !(found_guid && found_location && found_type)) { | |
| 51 if (!iapps::SeekToNodeAtCurrentDepth(reader, "key")) | 47 if (!iapps::SeekToNodeAtCurrentDepth(reader, "key")) |
| 52 break; | 48 break; |
| 53 std::string found_key; | 49 std::string found_key; |
| 54 if (!reader->ReadElementContent(&found_key)) | 50 if (!reader->ReadElementContent(&found_key)) |
| 55 break; | 51 break; |
| 56 DCHECK_EQ(dict_content_depth, reader->Depth()); | 52 DCHECK_EQ(dict_content_depth, reader->Depth()); |
| 57 | 53 |
| 58 if (found_key == "GUID") { | 54 if (found_key == "ImagePath") { |
| 59 if (found_guid) | |
| 60 break; | |
| 61 if (!iapps::ReadString(reader, &result->guid)) | |
| 62 break; | |
| 63 found_guid = true; | |
| 64 } else if (found_key == "MediaType") { | |
| 65 if (found_type) | |
| 66 break; | |
| 67 if (!iapps::ReadString(reader, &result->type)) | |
| 68 break; | |
| 69 found_type = true; | |
| 70 } else if (found_key == "ImagePath") { | |
| 71 if (found_location) | 55 if (found_location) |
| 72 break; | 56 break; |
| 73 std::string value; | 57 std::string value; |
| 74 if (!iapps::ReadString(reader, &value)) | 58 if (!iapps::ReadString(reader, &value)) |
| 75 break; | 59 break; |
| 76 result->location = base::FilePath(value); | 60 result->location = base::FilePath(value); |
| 77 found_location = true; | 61 found_location = true; |
| 62 } else if (found_key == "OriginalPath") { |
| 63 std::string value; |
| 64 if (!iapps::ReadString(reader, &value)) |
| 65 break; |
| 66 result->original_location = base::FilePath(value); |
| 78 } else { | 67 } else { |
| 79 if (!iapps::SkipToNextElement(reader)) | 68 if (!iapps::SkipToNextElement(reader)) |
| 80 break; | 69 break; |
| 81 if (!reader->Next()) | 70 if (!reader->Next()) |
| 82 break; | 71 break; |
| 83 } | 72 } |
| 84 } | 73 } |
| 85 | 74 |
| 86 // Seek to the end of the dictionary | 75 // Seek to the end of the dictionary |
| 87 while (reader->Depth() >= dict_content_depth) | 76 while (reader->Depth() >= dict_content_depth) |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 break; | 211 break; |
| 223 } | 212 } |
| 224 | 213 |
| 225 PhotoInfo photo_info; | 214 PhotoInfo photo_info; |
| 226 photo_info.id = id; | 215 photo_info.id = id; |
| 227 if (!GetPhotoInfoFromDict(reader, &photo_info)) { | 216 if (!GetPhotoInfoFromDict(reader, &photo_info)) { |
| 228 errors = true; | 217 errors = true; |
| 229 break; | 218 break; |
| 230 } | 219 } |
| 231 | 220 |
| 232 parser::Photo photo(photo_info.id, photo_info.location); | 221 parser::Photo photo(photo_info.id, photo_info.location, |
| 222 photo_info.original_location); |
| 233 all_photos->insert(photo); | 223 all_photos->insert(photo); |
| 234 } | 224 } |
| 235 | 225 |
| 236 return !errors; | 226 return !errors; |
| 237 } | 227 } |
| 238 | 228 |
| 239 } // namespace | 229 } // namespace |
| 240 | 230 |
| 241 IPhotoLibraryParser::IPhotoLibraryParser() {} | 231 IPhotoLibraryParser::IPhotoLibraryParser() {} |
| 242 IPhotoLibraryParser::~IPhotoLibraryParser() {} | 232 IPhotoLibraryParser::~IPhotoLibraryParser() {} |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 if (!iapps::SeekToNodeAtCurrentDepth(&reader, "array") || | 269 if (!iapps::SeekToNodeAtCurrentDepth(&reader, "array") || |
| 280 !reader.Read()) { | 270 !reader.Read()) { |
| 281 continue; | 271 continue; |
| 282 } | 272 } |
| 283 | 273 |
| 284 while (iapps::SeekToNodeAtCurrentDepth(&reader, "dict")) { | 274 while (iapps::SeekToNodeAtCurrentDepth(&reader, "dict")) { |
| 285 AlbumInfo album_info; | 275 AlbumInfo album_info; |
| 286 if (GetAlbumInfoFromDict(&reader, &album_info)) { | 276 if (GetAlbumInfoFromDict(&reader, &album_info)) { |
| 287 parser::Album album; | 277 parser::Album album; |
| 288 album = album_info.photo_ids; | 278 album = album_info.photo_ids; |
| 289 // Strip / from album name. | 279 // Strip / from album name and dedupe any collisions. |
| 290 std::string name; | 280 std::string name; |
| 291 ReplaceChars(album_info.name, "//", " ", &name); | 281 ReplaceChars(album_info.name, "//", " ", &name); |
| 292 library_.albums[name] = album; | 282 if (!ContainsKey(library_.albums, name)) { |
| 283 library_.albums[name] = album; |
| 284 } else { |
| 285 library_.albums[name+"("+base::Uint64ToString(album_info.id)+")"] = |
| 286 album; |
| 287 } |
| 293 } | 288 } |
| 294 } | 289 } |
| 295 } else if (found_key == "Master Image List") { | 290 } else if (found_key == "Master Image List") { |
| 296 if (found_photos) | 291 if (found_photos) |
| 297 continue; | 292 continue; |
| 298 found_photos = true; | 293 found_photos = true; |
| 299 if (!ParseAllPhotos(&reader, &library_.all_photos)) | 294 if (!ParseAllPhotos(&reader, &library_.all_photos)) |
| 300 return false; | 295 return false; |
| 301 } | 296 } |
| 302 } | 297 } |
| 303 | 298 |
| 304 return true; | 299 return true; |
| 305 } | 300 } |
| 306 | 301 |
| 307 } // namespace iphoto | 302 } // namespace iphoto |
| OLD | NEW |