18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file. 48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/utility/media_galleries/iapps_xml_utils.h" 68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/logging.h" 88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/stl_util.h" 98bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "third_party/libxml/chromium/libxml_utils.h" 118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace iapps { 138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool SkipToNextElement(XmlReader* reader) { 158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!reader->SkipToElement()) { 168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // SkipToElement returns false if the current node is an end element, 178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // try to advance to the next element and then try again. 188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!reader->Read() || !reader->SkipToElement()) 198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool SeekToNodeAtCurrentDepth(XmlReader* reader, const std::string& name) { 258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int depth = reader->Depth(); 268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) do { 278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!SkipToNextElement(reader) || reader->Depth() < depth) 288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK_EQ(depth, reader->Depth()); 308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (reader->NodeName() == name) 318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } while (reader->Next()); 338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool SeekInDict(XmlReader* reader, const std::string& key) { 388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK_EQ("dict", reader->NodeName()); 398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int dict_content_depth = reader->Depth() + 1; 418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Advance past the dict node and into the body of the dictionary. 428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!reader->Read()) 438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) while (reader->Depth() >= dict_content_depth) { 468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!SeekToNodeAtCurrentDepth(reader, "key")) 478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string found_key; 498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!reader->ReadElementContent(&found_key)) 508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK_EQ(dict_content_depth, reader->Depth()); 528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (found_key == key) 538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Seek to the start of a tag and read the value into |result| if the node's 598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// name is |node_name|. 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ReadSimpleValue(XmlReader* reader, const std::string& node_name, 618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string* result) { 628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!iapps::SkipToNextElement(reader)) 638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (reader->NodeName() != node_name) 658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return reader->ReadElementContent(result); 678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ReadString(XmlReader* reader, std::string* result) { 708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return ReadSimpleValue(reader, "string", result); 718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ReadInteger(XmlReader* reader, uint64* result) { 748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string value; 758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!ReadSimpleValue(reader, "integer", &value)) 768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return base::StringToUint64(value, result); 788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustd::string ReadFileAsString(base::File file) { 818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string result; 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!file.IsValid()) 838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return result; 848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // A "reasonable" artificial limit. 868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(vandebo): Add a UMA to figure out what common values are. 878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const int64 kMaxLibraryFileSize = 150 * 1024 * 1024; 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::File::Info file_info; 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!file.GetInfo(&file_info) || file_info.size > kMaxLibraryFileSize) 908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return result; 918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result.resize(file_info.size); 935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int bytes_read = file.Read(0, string_as_array(&result), file_info.size); 948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (bytes_read != file_info.size) 958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result.clear(); 968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return result; 988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)XmlDictReader::XmlDictReader(XmlReader* reader) : reader_(reader) {} 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)XmlDictReader::~XmlDictReader() {} 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool XmlDictReader::Read() { 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (reader_->NodeName() != "dict") 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int dict_content_depth = reader_->Depth() + 1; 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Advance past the dict node and into the body of the dictionary. 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!reader_->Read()) 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (reader_->Depth() >= dict_content_depth && ShouldLoop()) { 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!iapps::SeekToNodeAtCurrentDepth(reader_, "key")) 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string found_key; 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!reader_->ReadElementContent(&found_key)) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_EQ(dict_content_depth, reader_->Depth()); 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!HandleKey(found_key)) 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Seek to the end of the dictionary. Bail on end or error. 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (reader_->Depth() >= dict_content_depth && reader_->Next()) { 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return FinishedOk(); 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool XmlDictReader::ShouldLoop() { 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool XmlDictReader::HandleKey(const std::string& key) { 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (Found(key)) 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return AllowRepeats(); 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (HandleKeyImpl(key)) { 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) found_.insert(key); 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool XmlDictReader::AllowRepeats() { 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool XmlDictReader::FinishedOk() { 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool XmlDictReader::SkipToNext() { 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return SkipToNextElement(reader_) && reader_->Next(); 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool XmlDictReader::Found(const std::string& key) const { 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ContainsKey(found_, key); 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} // namespace iapps 161