15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/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" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.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) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kRootsKey = "roots"; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kRootFolderNameKey = "bookmark_bar"; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kOtherBookmarkFolderNameKey = "other"; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The value is left as 'synced' for historical reasons. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kMobileBookmarkFolderNameKey = "synced"; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kVersionKey = "version"; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kChecksumKey = "checksum"; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kIdKey = "id"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kTypeKey = "type"; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kNameKey = "name"; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kDateAddedKey = "date_added"; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kURLKey = "url"; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kDateModifiedKey = "date_modified"; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kChildrenKey = "children"; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kMetaInfo = "meta_info"; 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char* BookmarkCodec::kSyncTransactionVersion = "sync_transaction_version"; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kTypeURL = "url"; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kTypeFolder = "folder"; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Current version of the file. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCurrentVersion = 1; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkCodec::BookmarkCodec() 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ids_reassigned_(false), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_valid_(true), 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) maximum_id_(0), 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) model_sync_transaction_version_( 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::kInvalidSyncTransactionVersion) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkCodec::~BookmarkCodec() {} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Value* BookmarkCodec::Encode(BookmarkModel* model) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Encode(model->bookmark_bar_node(), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->other_node(), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->mobile_node(), 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) model->root_node()->GetMetaInfoMap(), 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) model->root_node()->sync_transaction_version()); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)Value* BookmarkCodec::Encode( 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode* bookmark_bar_node, 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode* other_folder_node, 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode* mobile_folder_node, 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode::MetaInfoMap* model_meta_info_map, 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64 sync_transaction_version) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_reassigned_ = false; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeChecksum(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* roots = new DictionaryValue(); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->Set(kMobileBookmarkFolderNameKey, EncodeNode(mobile_folder_node)); 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (model_meta_info_map) 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) roots->Set(kMetaInfo, EncodeMetaInfo(*model_meta_info_map)); 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (sync_transaction_version != 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::kInvalidSyncTransactionVersion) { 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) roots->SetString(kSyncTransactionVersion, 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Int64ToString(sync_transaction_version)); 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* main = new DictionaryValue(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main->SetInteger(kVersionKey, kCurrentVersion); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinalizeChecksum(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are going to store the computed checksum. So set stored checksum to be 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the same as computed checksum. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stored_checksum_ = computed_checksum_; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) main->Set(kChecksumKey, new base::StringValue(computed_checksum_)); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main->Set(kRootsKey, roots); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return main; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::Decode(BookmarkNode* bb_node, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* other_folder_node, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* mobile_folder_node, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64* max_id, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value& value) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_.clear(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_reassigned_ = false; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_valid_ = true; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_ = 0; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stored_checksum_.clear(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeChecksum(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = DecodeHelper(bb_node, other_folder_node, mobile_folder_node, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinalizeChecksum(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If either the checksums differ or some IDs were missing/not unique, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reassign IDs. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ids_valid_ || computed_checksum() != stored_checksum()) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDs(bb_node, other_folder_node, mobile_folder_node); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *max_id = maximum_id_ + 1; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* value = new DictionaryValue(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string id = base::Int64ToString(node->id()); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kIdKey, id); 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title = node->GetTitle(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kNameKey, title); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kDateAddedKey, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(node->date_added().ToInternalValue())); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->is_url()) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kTypeKey, kTypeURL); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url = node->url().possibly_invalid_spec(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kURLKey, url); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithUrlNode(id, title, url); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kTypeKey, kTypeFolder); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kDateModifiedKey, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(node->date_folder_modified(). 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToInternalValue())); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithFolderNode(id, title); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListValue* child_values = new ListValue(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->Set(kChildrenKey, child_values); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < node->child_count(); ++i) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_values->Append(EncodeNode(node->GetChild(i))); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode::MetaInfoMap* meta_info_map = node->GetMetaInfoMap(); 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (meta_info_map) 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) value->Set(kMetaInfo, EncodeMetaInfo(*meta_info_map)); 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (node->sync_transaction_version() != 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::kInvalidSyncTransactionVersion) { 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) value->SetString(kSyncTransactionVersion, 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Int64ToString(node->sync_transaction_version())); 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)base::Value* BookmarkCodec::EncodeMetaInfo( 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const BookmarkNode::MetaInfoMap& meta_info_map) { 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::DictionaryValue* meta_info = new base::DictionaryValue; 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (BookmarkNode::MetaInfoMap::const_iterator it = meta_info_map.begin(); 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it != meta_info_map.end(); ++it) { 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info->SetStringWithoutPathExpansion(it->first, it->second); 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return meta_info; 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* other_folder_node, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* mobile_folder_node, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value& value) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value.GetType() != Value::TYPE_DICTIONARY) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Unexpected type. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int version; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Unknown version. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* checksum_value; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (d_value.Get(kChecksumKey, &checksum_value)) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (checksum_value->GetType() != Value::TYPE_STRING) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!checksum_value->GetAsString(&stored_checksum_)) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* roots; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!d_value.Get(kRootsKey, &roots)) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No roots. 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (roots->GetType() != Value::TYPE_DICTIONARY) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Invalid type for roots. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryValue* roots_d_value = 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<const DictionaryValue*>(roots); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* root_folder_value; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* other_folder_value = NULL; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!roots_d_value->Get(kRootFolderNameKey, &root_folder_value) || 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root_folder_value->GetType() != Value::TYPE_DICTIONARY || 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !roots_d_value->Get(kOtherBookmarkFolderNameKey, &other_folder_value) || 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_value->GetType() != Value::TYPE_DICTIONARY) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Invalid type for root folder and/or other 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // folder. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNode(*static_cast<const DictionaryValue*>(root_folder_value), NULL, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bb_node); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNode(*static_cast<const DictionaryValue*>(other_folder_value), NULL, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_node); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fail silently if we can't deserialize mobile bookmarks. We can't require 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them to exist in order to be backwards-compatible with older versions of 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chrome. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* mobile_folder_value; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (roots_d_value->Get(kMobileBookmarkFolderNameKey, &mobile_folder_value) && 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_value->GetType() == Value::TYPE_DICTIONARY) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNode(*static_cast<const DictionaryValue*>(mobile_folder_value), NULL, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_node); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we didn't find the mobile folder, we're almost guaranteed to have a 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // duplicate id when we add the mobile folder. Consequently, if we don't 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // intend to reassign ids in the future (ids_valid_ is still true), then at 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // least reassign the mobile bookmarks to avoid it colliding with anything 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ids_valid_) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(mobile_folder_node); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!DecodeMetaInfo(*roots_d_value, &model_meta_info_map_, 221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &model_sync_transaction_version_)) 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string sync_transaction_version_str; 225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (roots_d_value->GetString(kSyncTransactionVersion, 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &sync_transaction_version_str) && 227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) !base::StringToInt64(sync_transaction_version_str, 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &model_sync_transaction_version_)) 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to reset the type as decoding resets the type to FOLDER. Similarly 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we need to reset the title as the title is persisted and restored from 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the file. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bb_node->set_type(BookmarkNode::BOOKMARK_BAR); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_node->set_type(BookmarkNode::OTHER_NODE); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_node->set_type(BookmarkNode::MOBILE); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bb_node->SetTitle(l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME)); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_node->SetTitle( 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OTHER_FOLDER_NAME)); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_node->SetTitle( 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_MOBILE_FOLDER_NAME)); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::DecodeChildren(const ListValue& child_value_list, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* parent) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < child_value_list.GetSize(); ++i) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* child_value; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!child_value_list.Get(i, &child_value)) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child_value->GetType() != Value::TYPE_DICTIONARY) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNode(*static_cast<const DictionaryValue*>(child_value), parent, NULL); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::DecodeNode(const DictionaryValue& value, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* parent, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* node) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If no |node| is specified, we'll create one and add it to the |parent|. 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Therefore, in that case, |parent| must be non-NULL. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node && !parent) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string id_string; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id = 0; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ids_valid_) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kIdKey, &id_string) || 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !base::StringToInt64(id_string, &id) || 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_.count(id) != 0) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_valid_ = false; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_.insert(id); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_ = std::max(maximum_id_, id); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 title; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value.GetString(kNameKey, &title); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string date_added_string; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kDateAddedKey, &date_added_string)) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) date_added_string = base::Int64ToString(Time::Now().ToInternalValue()); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 internal_time; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt64(date_added_string, &internal_time); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string type_string; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kTypeKey, &type_string)) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type_string != kTypeURL && type_string != kTypeFolder) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Unknown type. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type_string == kTypeURL) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_string; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kURLKey, &url_string)) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url = GURL(url_string); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node && url.is_valid()) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = new BookmarkNode(id, url); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Node invalid. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent->Add(node, parent->child_count()); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_type(BookmarkNode::URL); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithUrlNode(id_string, title, url_string); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string last_modified_date; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kDateModifiedKey, &last_modified_date)) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_modified_date = base::Int64ToString(Time::Now().ToInternalValue()); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* child_values; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.Get(kChildrenKey, &child_values)) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child_values->GetType() != Value::TYPE_LIST) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = new BookmarkNode(id, GURL()); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a new node is not created, explicitly assign ID to the existing one. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_id(id); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_type(BookmarkNode::FOLDER); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 internal_time; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt64(last_modified_date, &internal_time); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_date_folder_modified(Time::FromInternalValue(internal_time)); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent->Add(node, parent->child_count()); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithFolderNode(id_string, title); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!DecodeChildren(*static_cast<const ListValue*>(child_values), node)) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->SetTitle(title); 35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) node->set_date_added(base::Time::FromInternalValue(internal_time)); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64 sync_transaction_version = node->sync_transaction_version(); 353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::MetaInfoMap meta_info_map; 354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!DecodeMetaInfo(value, &meta_info_map, &sync_transaction_version)) 355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) node->SetMetaInfoMap(meta_info_map); 357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string sync_transaction_version_str; 359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (value.GetString(kSyncTransactionVersion, &sync_transaction_version_str) && 360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) !base::StringToInt64(sync_transaction_version_str, 361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &sync_transaction_version)) 362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) node->set_sync_transaction_version(sync_transaction_version); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool BookmarkCodec::DecodeMetaInfo(const base::DictionaryValue& value, 370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::MetaInfoMap* meta_info_map, 371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64* sync_transaction_version) { 372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(meta_info_map); 373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(sync_transaction_version); 374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info_map->clear(); 375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::Value* meta_info; 377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!value.Get(kMetaInfo, &meta_info)) 378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<base::Value> deserialized_holder; 381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Meta info used to be stored as a serialized dictionary, so attempt to 383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // parse the value as one. 384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (meta_info->IsType(base::Value::TYPE_STRING)) { 385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string meta_info_str; 386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info->GetAsString(&meta_info_str); 387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) JSONStringValueSerializer serializer(meta_info_str); 388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) deserialized_holder.reset(serializer.Deserialize(NULL, NULL)); 389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!deserialized_holder) 390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info = deserialized_holder.get(); 392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // meta_info is now either the kMetaInfo node, or the deserialized node if it 394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // was stored as a string. Either way it should now be a (possibly nested) 395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // dictionary of meta info values. 396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::DictionaryValue* meta_info_dict; 397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!meta_info->GetAsDictionary(&meta_info_dict)) 398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DecodeMetaInfoHelper(*meta_info_dict, std::string(), meta_info_map); 400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Previously sync transaction version was stored in the meta info field 402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // using this key. If the key is present when decoding, set the sync 403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // transaction version to its value, then delete the field. 404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (deserialized_holder) { 405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const char kBookmarkTransactionVersionKey[] = "sync.transaction_version"; 406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::MetaInfoMap::iterator it = 407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info_map->find(kBookmarkTransactionVersionKey); 408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (it != meta_info_map->end()) { 409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::StringToInt64(it->second, sync_transaction_version); 410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meta_info_map->erase(it); 411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void BookmarkCodec::DecodeMetaInfoHelper( 418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::DictionaryValue& dict, 419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& prefix, 420f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BookmarkNode::MetaInfoMap* meta_info_map) { 421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { 422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (it.value().IsType(base::Value::TYPE_DICTIONARY)) { 423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::DictionaryValue* subdict; 424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it.value().GetAsDictionary(&subdict); 425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DecodeMetaInfoHelper(*subdict, prefix + it.key() + ".", meta_info_map); 426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (it.value().IsType(base::Value::TYPE_STRING)) { 427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it.value().GetAsString(&(*meta_info_map)[prefix + it.key()]); 428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 429f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::ReassignIDs(BookmarkNode* bb_node, 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* other_node, 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* mobile_node) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_ = 0; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(bb_node); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(other_node); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(mobile_node); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_reassigned_ = true; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::ReassignIDsHelper(BookmarkNode* node) { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(node); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_id(++maximum_id_); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < node->child_count(); ++i) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(node->GetChild(i)); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksum(const std::string& str) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Update(&md5_context_, str); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BookmarkCodec::UpdateChecksum(const base::string16& str) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Update(&md5_context_, 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece( 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(str.data()), 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str.length() * sizeof(str[0]))); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksumWithUrlNode(const std::string& id, 461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title, 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsStringUTF8(url)); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(id); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(title); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(kTypeURL); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(url); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksumWithFolderNode(const std::string& id, 471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(id); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(title); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(kTypeFolder); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::InitializeChecksum() { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Init(&md5_context_); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::FinalizeChecksum() { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Digest digest; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Final(&digest, &md5_context_); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) computed_checksum_ = base::MD5DigestToBase16(digest); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 486