15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_codec.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/json/json_string_value_serializer.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_model.h" 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "grit/components_strings.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)namespace bookmarks { 216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kRootsKey = "roots"; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kRootFolderNameKey = "bookmark_bar"; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kOtherBookmarkFolderNameKey = "other"; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The value is left as 'synced' for historical reasons. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kMobileBookmarkFolderNameKey = "synced"; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kVersionKey = "version"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kChecksumKey = "checksum"; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kIdKey = "id"; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kTypeKey = "type"; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kNameKey = "name"; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kDateAddedKey = "date_added"; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kURLKey = "url"; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kDateModifiedKey = "date_modified"; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kChildrenKey = "children"; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kMetaInfo = "meta_info"; 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char* BookmarkCodec::kSyncTransactionVersion = "sync_transaction_version"; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kTypeURL = "url"; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kTypeFolder = "folder"; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Current version of the file. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCurrentVersion = 1; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkCodec::BookmarkCodec() 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ids_reassigned_(false), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_valid_(true), 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) maximum_id_(0), 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) model_sync_transaction_version_( 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::kInvalidSyncTransactionVersion) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkCodec::~BookmarkCodec() {} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::Value* BookmarkCodec::Encode(BookmarkModel* model) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Encode(model->bookmark_bar_node(), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->other_node(), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->mobile_node(), 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) model->root_node()->GetMetaInfoMap(), 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) model->root_node()->sync_transaction_version()); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::Value* BookmarkCodec::Encode( 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode* bookmark_bar_node, 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode* other_folder_node, 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode* mobile_folder_node, 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode::MetaInfoMap* model_meta_info_map, 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64 sync_transaction_version) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_reassigned_ = false; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeChecksum(); 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* roots = new base::DictionaryValue(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->Set(kMobileBookmarkFolderNameKey, EncodeNode(mobile_folder_node)); 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (model_meta_info_map) 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) roots->Set(kMetaInfo, EncodeMetaInfo(*model_meta_info_map)); 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (sync_transaction_version != 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::kInvalidSyncTransactionVersion) { 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) roots->SetString(kSyncTransactionVersion, 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Int64ToString(sync_transaction_version)); 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* main = new base::DictionaryValue(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main->SetInteger(kVersionKey, kCurrentVersion); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinalizeChecksum(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are going to store the computed checksum. So set stored checksum to be 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the same as computed checksum. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stored_checksum_ = computed_checksum_; 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) main->Set(kChecksumKey, new base::StringValue(computed_checksum_)); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main->Set(kRootsKey, roots); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return main; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::Decode(BookmarkNode* bb_node, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* other_folder_node, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* mobile_folder_node, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64* max_id, 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value& value) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_.clear(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_reassigned_ = false; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_valid_ = true; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_ = 0; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stored_checksum_.clear(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeChecksum(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = DecodeHelper(bb_node, other_folder_node, mobile_folder_node, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinalizeChecksum(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If either the checksums differ or some IDs were missing/not unique, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reassign IDs. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ids_valid_ || computed_checksum() != stored_checksum()) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDs(bb_node, other_folder_node, mobile_folder_node); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *max_id = maximum_id_ + 1; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* value = new base::DictionaryValue(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string id = base::Int64ToString(node->id()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kIdKey, id); 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title = node->GetTitle(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kNameKey, title); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kDateAddedKey, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(node->date_added().ToInternalValue())); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->is_url()) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kTypeKey, kTypeURL); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url = node->url().possibly_invalid_spec(); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kURLKey, url); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithUrlNode(id, title, url); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kTypeKey, kTypeFolder); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kDateModifiedKey, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(node->date_folder_modified(). 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToInternalValue())); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithFolderNode(id, title); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue* child_values = new base::ListValue(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->Set(kChildrenKey, child_values); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < node->child_count(); ++i) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_values->Append(EncodeNode(node->GetChild(i))); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode::MetaInfoMap* meta_info_map = node->GetMetaInfoMap(); 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (meta_info_map) 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) value->Set(kMetaInfo, EncodeMetaInfo(*meta_info_map)); 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (node->sync_transaction_version() != 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::kInvalidSyncTransactionVersion) { 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) value->SetString(kSyncTransactionVersion, 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Int64ToString(node->sync_transaction_version())); 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)base::Value* BookmarkCodec::EncodeMetaInfo( 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode::MetaInfoMap& meta_info_map) { 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::DictionaryValue* meta_info = new base::DictionaryValue; 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (BookmarkNode::MetaInfoMap::const_iterator it = meta_info_map.begin(); 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it != meta_info_map.end(); ++it) { 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info->SetStringWithoutPathExpansion(it->first, it->second); 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return meta_info; 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* other_folder_node, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* mobile_folder_node, 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value& value) { 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (value.GetType() != base::Value::TYPE_DICTIONARY) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Unexpected type. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue& d_value = 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<const base::DictionaryValue&>(value); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int version; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Unknown version. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* checksum_value; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (d_value.Get(kChecksumKey, &checksum_value)) { 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (checksum_value->GetType() != base::Value::TYPE_STRING) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!checksum_value->GetAsString(&stored_checksum_)) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* roots; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!d_value.Get(kRootsKey, &roots)) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No roots. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (roots->GetType() != base::Value::TYPE_DICTIONARY) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Invalid type for roots. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* roots_d_value = 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<const base::DictionaryValue*>(roots); 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* root_folder_value; 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* other_folder_value = NULL; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!roots_d_value->Get(kRootFolderNameKey, &root_folder_value) || 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) root_folder_value->GetType() != base::Value::TYPE_DICTIONARY || 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !roots_d_value->Get(kOtherBookmarkFolderNameKey, &other_folder_value) || 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) other_folder_value->GetType() != base::Value::TYPE_DICTIONARY) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Invalid type for root folder and/or other 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // folder. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DecodeNode(*static_cast<const base::DictionaryValue*>(root_folder_value), 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, bb_node); 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DecodeNode(*static_cast<const base::DictionaryValue*>(other_folder_value), 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, other_folder_node); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fail silently if we can't deserialize mobile bookmarks. We can't require 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them to exist in order to be backwards-compatible with older versions of 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chrome. 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* mobile_folder_value; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (roots_d_value->Get(kMobileBookmarkFolderNameKey, &mobile_folder_value) && 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mobile_folder_value->GetType() == base::Value::TYPE_DICTIONARY) { 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DecodeNode(*static_cast<const base::DictionaryValue*>(mobile_folder_value), 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, mobile_folder_node); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we didn't find the mobile folder, we're almost guaranteed to have a 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // duplicate id when we add the mobile folder. Consequently, if we don't 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // intend to reassign ids in the future (ids_valid_ is still true), then at 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // least reassign the mobile bookmarks to avoid it colliding with anything 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ids_valid_) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(mobile_folder_node); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!DecodeMetaInfo(*roots_d_value, &model_meta_info_map_, 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &model_sync_transaction_version_)) 225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string sync_transaction_version_str; 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (roots_d_value->GetString(kSyncTransactionVersion, 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &sync_transaction_version_str) && 230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) !base::StringToInt64(sync_transaction_version_str, 231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &model_sync_transaction_version_)) 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to reset the type as decoding resets the type to FOLDER. Similarly 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we need to reset the title as the title is persisted and restored from 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the file. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bb_node->set_type(BookmarkNode::BOOKMARK_BAR); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_node->set_type(BookmarkNode::OTHER_NODE); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_node->set_type(BookmarkNode::MOBILE); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bb_node->SetTitle(l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME)); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_node->SetTitle( 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OTHER_FOLDER_NAME)); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_node->SetTitle( 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_MOBILE_FOLDER_NAME)); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BookmarkCodec::DecodeChildren(const base::ListValue& child_value_list, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* parent) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < child_value_list.GetSize(); ++i) { 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* child_value; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!child_value_list.Get(i, &child_value)) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (child_value->GetType() != base::Value::TYPE_DICTIONARY) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DecodeNode(*static_cast<const base::DictionaryValue*>(child_value), 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parent, NULL); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BookmarkCodec::DecodeNode(const base::DictionaryValue& value, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* parent, 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* node) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If no |node| is specified, we'll create one and add it to the |parent|. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Therefore, in that case, |parent| must be non-NULL. 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node && !parent) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string id_string; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id = 0; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ids_valid_) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kIdKey, &id_string) || 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !base::StringToInt64(id_string, &id) || 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_.count(id) != 0) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_valid_ = false; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_.insert(id); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_ = std::max(maximum_id_, id); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 title; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value.GetString(kNameKey, &title); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string date_added_string; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kDateAddedKey, &date_added_string)) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) date_added_string = base::Int64ToString(Time::Now().ToInternalValue()); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 internal_time; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt64(date_added_string, &internal_time); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string type_string; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kTypeKey, &type_string)) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type_string != kTypeURL && type_string != kTypeFolder) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Unknown type. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type_string == kTypeURL) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_string; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kURLKey, &url_string)) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url = GURL(url_string); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node && url.is_valid()) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = new BookmarkNode(id, url); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Node invalid. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent->Add(node, parent->child_count()); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_type(BookmarkNode::URL); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithUrlNode(id_string, title, url_string); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string last_modified_date; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kDateModifiedKey, &last_modified_date)) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_modified_date = base::Int64ToString(Time::Now().ToInternalValue()); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* child_values; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.Get(kChildrenKey, &child_values)) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (child_values->GetType() != base::Value::TYPE_LIST) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = new BookmarkNode(id, GURL()); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a new node is not created, explicitly assign ID to the existing one. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_id(id); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_type(BookmarkNode::FOLDER); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 internal_time; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt64(last_modified_date, &internal_time); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_date_folder_modified(Time::FromInternalValue(internal_time)); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent->Add(node, parent->child_count()); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithFolderNode(id_string, title); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!DecodeChildren(*static_cast<const base::ListValue*>(child_values), 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) node)) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->SetTitle(title); 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) node->set_date_added(Time::FromInternalValue(internal_time)); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64 sync_transaction_version = node->sync_transaction_version(); 359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::MetaInfoMap meta_info_map; 360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!DecodeMetaInfo(value, &meta_info_map, &sync_transaction_version)) 361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) node->SetMetaInfoMap(meta_info_map); 363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string sync_transaction_version_str; 365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (value.GetString(kSyncTransactionVersion, &sync_transaction_version_str) && 366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) !base::StringToInt64(sync_transaction_version_str, 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &sync_transaction_version)) 368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) node->set_sync_transaction_version(sync_transaction_version); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool BookmarkCodec::DecodeMetaInfo(const base::DictionaryValue& value, 376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::MetaInfoMap* meta_info_map, 377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64* sync_transaction_version) { 378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(meta_info_map); 379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(sync_transaction_version); 380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info_map->clear(); 381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::Value* meta_info; 383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!value.Get(kMetaInfo, &meta_info)) 384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<base::Value> deserialized_holder; 387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Meta info used to be stored as a serialized dictionary, so attempt to 389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // parse the value as one. 390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (meta_info->IsType(base::Value::TYPE_STRING)) { 391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string meta_info_str; 392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info->GetAsString(&meta_info_str); 393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) JSONStringValueSerializer serializer(meta_info_str); 394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) deserialized_holder.reset(serializer.Deserialize(NULL, NULL)); 395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!deserialized_holder) 396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info = deserialized_holder.get(); 398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // meta_info is now either the kMetaInfo node, or the deserialized node if it 400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // was stored as a string. Either way it should now be a (possibly nested) 401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // dictionary of meta info values. 402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::DictionaryValue* meta_info_dict; 403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!meta_info->GetAsDictionary(&meta_info_dict)) 404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DecodeMetaInfoHelper(*meta_info_dict, std::string(), meta_info_map); 406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Previously sync transaction version was stored in the meta info field 408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // using this key. If the key is present when decoding, set the sync 409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // transaction version to its value, then delete the field. 410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (deserialized_holder) { 411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const char kBookmarkTransactionVersionKey[] = "sync.transaction_version"; 412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::MetaInfoMap::iterator it = 413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info_map->find(kBookmarkTransactionVersionKey); 414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (it != meta_info_map->end()) { 415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::StringToInt64(it->second, sync_transaction_version); 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info_map->erase(it); 417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 420f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void BookmarkCodec::DecodeMetaInfoHelper( 424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::DictionaryValue& dict, 425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& prefix, 426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::MetaInfoMap* meta_info_map) { 427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { 428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (it.value().IsType(base::Value::TYPE_DICTIONARY)) { 429f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::DictionaryValue* subdict; 430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it.value().GetAsDictionary(&subdict); 431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DecodeMetaInfoHelper(*subdict, prefix + it.key() + ".", meta_info_map); 432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (it.value().IsType(base::Value::TYPE_STRING)) { 433f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it.value().GetAsString(&(*meta_info_map)[prefix + it.key()]); 434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 436f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::ReassignIDs(BookmarkNode* bb_node, 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* other_node, 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* mobile_node) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_ = 0; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(bb_node); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(other_node); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(mobile_node); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_reassigned_ = true; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::ReassignIDsHelper(BookmarkNode* node) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(node); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_id(++maximum_id_); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < node->child_count(); ++i) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(node->GetChild(i)); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksum(const std::string& str) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Update(&md5_context_, str); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BookmarkCodec::UpdateChecksum(const base::string16& str) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Update(&md5_context_, 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece( 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(str.data()), 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str.length() * sizeof(str[0]))); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksumWithUrlNode(const std::string& id, 467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url) { 469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(base::IsStringUTF8(url)); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(id); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(title); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(kTypeURL); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(url); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksumWithFolderNode(const std::string& id, 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(id); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(title); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(kTypeFolder); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::InitializeChecksum() { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Init(&md5_context_); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::FinalizeChecksum() { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Digest digest; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Final(&digest, &md5_context_); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) computed_checksum_ = base::MD5DigestToBase16(digest); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} // namespace bookmarks 494