bookmark_codec.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kRootsKey = "roots"; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kRootFolderNameKey = "bookmark_bar"; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kOtherBookmarkFolderNameKey = "other"; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The value is left as 'synced' for historical reasons. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kMobileBookmarkFolderNameKey = "synced"; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kVersionKey = "version"; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kChecksumKey = "checksum"; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kIdKey = "id"; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kTypeKey = "type"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kNameKey = "name"; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kDateAddedKey = "date_added"; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kURLKey = "url"; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kDateModifiedKey = "date_modified"; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kChildrenKey = "children"; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kMetaInfo = "meta_info"; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kTypeURL = "url"; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BookmarkCodec::kTypeFolder = "folder"; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Current version of the file. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCurrentVersion = 1; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkCodec::BookmarkCodec() 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ids_reassigned_(false), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_valid_(true), 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_(0) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkCodec::~BookmarkCodec() {} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Value* BookmarkCodec::Encode(BookmarkModel* model) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Encode(model->bookmark_bar_node(), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->other_node(), 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->mobile_node(), 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->root_node()->meta_info_str()); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Value* BookmarkCodec::Encode(const BookmarkNode* bookmark_bar_node, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* other_folder_node, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* mobile_folder_node, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& model_meta_info) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_reassigned_ = false; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeChecksum(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* roots = new DictionaryValue(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->Set(kMobileBookmarkFolderNameKey, EncodeNode(mobile_folder_node)); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!model_meta_info.empty()) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots->SetString(kMetaInfo, model_meta_info); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* main = new DictionaryValue(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main->SetInteger(kVersionKey, kCurrentVersion); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinalizeChecksum(); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are going to store the computed checksum. So set stored checksum to be 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the same as computed checksum. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stored_checksum_ = computed_checksum_; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) main->Set(kChecksumKey, new base::StringValue(computed_checksum_)); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main->Set(kRootsKey, roots); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return main; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::Decode(BookmarkNode* bb_node, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* other_folder_node, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* mobile_folder_node, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64* max_id, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value& value) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_.clear(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_reassigned_ = false; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_valid_ = true; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_ = 0; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stored_checksum_.clear(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeChecksum(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = DecodeHelper(bb_node, other_folder_node, mobile_folder_node, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinalizeChecksum(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If either the checksums differ or some IDs were missing/not unique, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reassign IDs. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ids_valid_ || computed_checksum() != stored_checksum()) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDs(bb_node, other_folder_node, mobile_folder_node); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *max_id = maximum_id_ + 1; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* value = new DictionaryValue(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string id = base::Int64ToString(node->id()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kIdKey, id); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title = node->GetTitle(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kNameKey, title); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kDateAddedKey, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(node->date_added().ToInternalValue())); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->is_url()) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kTypeKey, kTypeURL); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url = node->url().possibly_invalid_spec(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kURLKey, url); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithUrlNode(id, title, url); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kTypeKey, kTypeFolder); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kDateModifiedKey, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(node->date_folder_modified(). 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToInternalValue())); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithFolderNode(id, title); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListValue* child_values = new ListValue(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->Set(kChildrenKey, child_values); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < node->child_count(); ++i) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_values->Append(EncodeNode(node->GetChild(i))); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node->meta_info_str().empty()) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->SetString(kMetaInfo, node->meta_info_str()); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* other_folder_node, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* mobile_folder_node, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value& value) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value.GetType() != Value::TYPE_DICTIONARY) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Unexpected type. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int version; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Unknown version. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* checksum_value; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (d_value.Get(kChecksumKey, &checksum_value)) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (checksum_value->GetType() != Value::TYPE_STRING) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!checksum_value->GetAsString(&stored_checksum_)) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* roots; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!d_value.Get(kRootsKey, &roots)) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No roots. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (roots->GetType() != Value::TYPE_DICTIONARY) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Invalid type for roots. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryValue* roots_d_value = 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<const DictionaryValue*>(roots); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* root_folder_value; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* other_folder_value = NULL; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!roots_d_value->Get(kRootFolderNameKey, &root_folder_value) || 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root_folder_value->GetType() != Value::TYPE_DICTIONARY || 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !roots_d_value->Get(kOtherBookmarkFolderNameKey, &other_folder_value) || 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_value->GetType() != Value::TYPE_DICTIONARY) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Invalid type for root folder and/or other 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // folder. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNode(*static_cast<const DictionaryValue*>(root_folder_value), NULL, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bb_node); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNode(*static_cast<const DictionaryValue*>(other_folder_value), NULL, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_node); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fail silently if we can't deserialize mobile bookmarks. We can't require 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them to exist in order to be backwards-compatible with older versions of 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chrome. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* mobile_folder_value; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (roots_d_value->Get(kMobileBookmarkFolderNameKey, &mobile_folder_value) && 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_value->GetType() == Value::TYPE_DICTIONARY) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNode(*static_cast<const DictionaryValue*>(mobile_folder_value), NULL, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_node); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we didn't find the mobile folder, we're almost guaranteed to have a 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // duplicate id when we add the mobile folder. Consequently, if we don't 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // intend to reassign ids in the future (ids_valid_ is still true), then at 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // least reassign the mobile bookmarks to avoid it colliding with anything 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ids_valid_) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(mobile_folder_node); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) roots_d_value->GetString(kMetaInfo, &model_meta_info_); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to reset the type as decoding resets the type to FOLDER. Similarly 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we need to reset the title as the title is persisted and restored from 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the file. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bb_node->set_type(BookmarkNode::BOOKMARK_BAR); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_node->set_type(BookmarkNode::OTHER_NODE); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_node->set_type(BookmarkNode::MOBILE); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bb_node->SetTitle(l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME)); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_folder_node->SetTitle( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OTHER_FOLDER_NAME)); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mobile_folder_node->SetTitle( 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_MOBILE_FOLDER_NAME)); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::DecodeChildren(const ListValue& child_value_list, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* parent) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < child_value_list.GetSize(); ++i) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* child_value; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!child_value_list.Get(i, &child_value)) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child_value->GetType() != Value::TYPE_DICTIONARY) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNode(*static_cast<const DictionaryValue*>(child_value), parent, NULL); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkCodec::DecodeNode(const DictionaryValue& value, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* parent, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* node) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If no |node| is specified, we'll create one and add it to the |parent|. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Therefore, in that case, |parent| must be non-NULL. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node && !parent) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string id_string; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id = 0; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ids_valid_) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kIdKey, &id_string) || 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !base::StringToInt64(id_string, &id) || 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_.count(id) != 0) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_valid_ = false; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_.insert(id); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_ = std::max(maximum_id_, id); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 title; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value.GetString(kNameKey, &title); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string date_added_string; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kDateAddedKey, &date_added_string)) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) date_added_string = base::Int64ToString(Time::Now().ToInternalValue()); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 internal_time; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt64(date_added_string, &internal_time); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string type_string; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kTypeKey, &type_string)) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type_string != kTypeURL && type_string != kTypeFolder) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Unknown type. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type_string == kTypeURL) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_string; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kURLKey, &url_string)) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url = GURL(url_string); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node && url.is_valid()) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = new BookmarkNode(id, url); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Node invalid. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent->Add(node, parent->child_count()); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_type(BookmarkNode::URL); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithUrlNode(id_string, title, url_string); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string last_modified_date; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetString(kDateModifiedKey, &last_modified_date)) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_modified_date = base::Int64ToString(Time::Now().ToInternalValue()); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* child_values; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.Get(kChildrenKey, &child_values)) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child_values->GetType() != Value::TYPE_LIST) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = new BookmarkNode(id, GURL()); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a new node is not created, explicitly assign ID to the existing one. 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_id(id); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_type(BookmarkNode::FOLDER); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 internal_time; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt64(last_modified_date, &internal_time); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_date_folder_modified(Time::FromInternalValue(internal_time)); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent->Add(node, parent->child_count()); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksumWithFolderNode(id_string, title); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!DecodeChildren(*static_cast<const ListValue*>(child_values), node)) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->SetTitle(title); 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) node->set_date_added(base::Time::FromInternalValue(internal_time)); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string meta_info; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value.GetString(kMetaInfo, &meta_info)) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_meta_info_str(meta_info); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::ReassignIDs(BookmarkNode* bb_node, 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* other_node, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode* mobile_node) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximum_id_ = 0; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(bb_node); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(other_node); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(mobile_node); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_reassigned_ = true; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::ReassignIDsHelper(BookmarkNode* node) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(node); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->set_id(++maximum_id_); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < node->child_count(); ++i) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReassignIDsHelper(node->GetChild(i)); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksum(const std::string& str) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Update(&md5_context_, str); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksum(const string16& str) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Update(&md5_context_, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece( 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(str.data()), 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str.length() * sizeof(str[0]))); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksumWithUrlNode(const std::string& id, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsStringUTF8(url)); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(id); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(title); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(kTypeURL); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(url); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::UpdateChecksumWithFolderNode(const std::string& id, 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(id); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(title); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChecksum(kTypeFolder); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::InitializeChecksum() { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Init(&md5_context_); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarkCodec::FinalizeChecksum() { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Digest digest; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Final(&digest, &md5_context_); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) computed_checksum_ = base::MD5DigestToBase16(digest); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 376