Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/bookmarks/bookmark_codec.h" | 5 #include "chrome/browser/bookmarks/bookmark_codec.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 | |
| 7 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
| 8 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 9 #include "base/values.h" | 11 #include "base/values.h" |
| 10 #include "chrome/browser/bookmarks/bookmark_model.h" | 12 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 11 #include "googleurl/src/gurl.h" | 13 #include "googleurl/src/gurl.h" |
| 12 #include "grit/generated_resources.h" | 14 #include "grit/generated_resources.h" |
| 13 | 15 |
| 14 using base::Time; | 16 using base::Time; |
| 15 | 17 |
| 16 UniqueIDGenerator::UniqueIDGenerator() { | |
| 17 Reset(); | |
| 18 } | |
| 19 | |
| 20 int64 UniqueIDGenerator::GetUniqueID(int64 id) { | |
| 21 // If the given ID is already assigned, generate new ID. | |
| 22 if (IsIdAssigned(id)) | |
| 23 id = current_max_ + 1; | |
| 24 | |
| 25 // Record the new ID as assigned. | |
| 26 RecordId(id); | |
| 27 | |
| 28 if (id > current_max_) | |
| 29 current_max_ = id; | |
| 30 | |
| 31 return id; | |
| 32 } | |
| 33 | |
| 34 bool UniqueIDGenerator::IsIdAssigned(int64 id) const { | |
| 35 // If the set is already instantiated, then use the set to determine if the | |
| 36 // given ID is assigned. Otherwise use the current maximum to determine if the | |
| 37 // given ID is assigned. | |
| 38 if (assigned_ids_.get()) | |
| 39 return assigned_ids_->find(id) != assigned_ids_->end(); | |
| 40 else | |
| 41 return id <= current_max_; | |
| 42 } | |
| 43 | |
| 44 void UniqueIDGenerator::RecordId(int64 id) { | |
| 45 // If the set is instantiated, then use the set. | |
| 46 if (assigned_ids_.get()) { | |
| 47 assigned_ids_->insert(id); | |
| 48 return; | |
| 49 } | |
| 50 | |
| 51 // The set is not yet instantiated. If the ID is current_max_ + 1, then just | |
| 52 // update the current_max_. Otherwise, instantiate the set and add all IDs | |
| 53 // from 0 to current_max_ to it. | |
| 54 if (id == current_max_ + 1) { | |
| 55 ++current_max_; | |
| 56 return; | |
| 57 } | |
| 58 assigned_ids_.reset(new std::set<int64>); | |
| 59 for (int64 i = 0; i <= current_max_; ++i) | |
| 60 assigned_ids_->insert(i); | |
| 61 assigned_ids_->insert(id); | |
| 62 } | |
| 63 | |
| 64 void UniqueIDGenerator::Reset() { | |
| 65 current_max_ = 0; | |
| 66 assigned_ids_.reset(NULL); | |
| 67 } | |
| 68 | |
| 69 const wchar_t* BookmarkCodec::kRootsKey = L"roots"; | 18 const wchar_t* BookmarkCodec::kRootsKey = L"roots"; |
| 70 const wchar_t* BookmarkCodec::kRootFolderNameKey = L"bookmark_bar"; | 19 const wchar_t* BookmarkCodec::kRootFolderNameKey = L"bookmark_bar"; |
| 71 const wchar_t* BookmarkCodec::kOtherBookmarkFolderNameKey = L"other"; | 20 const wchar_t* BookmarkCodec::kOtherBookmarkFolderNameKey = L"other"; |
| 72 const wchar_t* BookmarkCodec::kVersionKey = L"version"; | 21 const wchar_t* BookmarkCodec::kVersionKey = L"version"; |
| 73 const wchar_t* BookmarkCodec::kChecksumKey = L"checksum"; | 22 const wchar_t* BookmarkCodec::kChecksumKey = L"checksum"; |
| 74 const wchar_t* BookmarkCodec::kIdKey = L"id"; | 23 const wchar_t* BookmarkCodec::kIdKey = L"id"; |
| 75 const wchar_t* BookmarkCodec::kTypeKey = L"type"; | 24 const wchar_t* BookmarkCodec::kTypeKey = L"type"; |
| 76 const wchar_t* BookmarkCodec::kNameKey = L"name"; | 25 const wchar_t* BookmarkCodec::kNameKey = L"name"; |
| 77 const wchar_t* BookmarkCodec::kDateAddedKey = L"date_added"; | 26 const wchar_t* BookmarkCodec::kDateAddedKey = L"date_added"; |
| 78 const wchar_t* BookmarkCodec::kURLKey = L"url"; | 27 const wchar_t* BookmarkCodec::kURLKey = L"url"; |
| 79 const wchar_t* BookmarkCodec::kDateModifiedKey = L"date_modified"; | 28 const wchar_t* BookmarkCodec::kDateModifiedKey = L"date_modified"; |
| 80 const wchar_t* BookmarkCodec::kChildrenKey = L"children"; | 29 const wchar_t* BookmarkCodec::kChildrenKey = L"children"; |
| 81 const wchar_t* BookmarkCodec::kTypeURL = L"url"; | 30 const wchar_t* BookmarkCodec::kTypeURL = L"url"; |
| 82 const wchar_t* BookmarkCodec::kTypeFolder = L"folder"; | 31 const wchar_t* BookmarkCodec::kTypeFolder = L"folder"; |
| 83 | 32 |
| 84 // Current version of the file. | 33 // Current version of the file. |
| 85 static const int kCurrentVersion = 1; | 34 static const int kCurrentVersion = 1; |
| 86 | 35 |
| 87 BookmarkCodec::BookmarkCodec() | 36 BookmarkCodec::BookmarkCodec() |
| 88 : ids_reassigned_(false) { | 37 : ids_reassigned_(false), |
| 38 ids_missing_(false), | |
| 39 maximum_id_(0) { | |
| 89 } | 40 } |
| 90 | 41 |
| 91 Value* BookmarkCodec::Encode(BookmarkModel* model) { | 42 Value* BookmarkCodec::Encode(BookmarkModel* model) { |
| 92 return Encode(model->GetBookmarkBarNode(), model->other_node()); | 43 return Encode(model->GetBookmarkBarNode(), model->other_node()); |
| 93 } | 44 } |
| 94 | 45 |
| 95 Value* BookmarkCodec::Encode(const BookmarkNode* bookmark_bar_node, | 46 Value* BookmarkCodec::Encode(const BookmarkNode* bookmark_bar_node, |
| 96 const BookmarkNode* other_folder_node) { | 47 const BookmarkNode* other_folder_node) { |
| 97 ids_reassigned_ = false; | 48 ids_reassigned_ = false; |
| 98 InitializeChecksum(); | 49 InitializeChecksum(); |
| 99 DictionaryValue* roots = new DictionaryValue(); | 50 DictionaryValue* roots = new DictionaryValue(); |
| 100 roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); | 51 roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); |
| 101 roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); | 52 roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); |
| 102 | 53 |
| 103 DictionaryValue* main = new DictionaryValue(); | 54 DictionaryValue* main = new DictionaryValue(); |
| 104 main->SetInteger(kVersionKey, kCurrentVersion); | 55 main->SetInteger(kVersionKey, kCurrentVersion); |
| 105 FinalizeChecksum(); | 56 FinalizeChecksum(); |
| 106 // We are going to store the computed checksum. So set stored checksum to be | 57 // We are going to store the computed checksum. So set stored checksum to be |
| 107 // the same as computed checksum. | 58 // the same as computed checksum. |
| 108 stored_checksum_ = computed_checksum_; | 59 stored_checksum_ = computed_checksum_; |
| 109 main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_)); | 60 main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_)); |
| 110 main->Set(kRootsKey, roots); | 61 main->Set(kRootsKey, roots); |
| 111 return main; | 62 return main; |
| 112 } | 63 } |
| 113 | 64 |
| 114 bool BookmarkCodec::Decode(BookmarkNode* bb_node, | 65 bool BookmarkCodec::Decode(BookmarkNode* bb_node, |
| 115 BookmarkNode* other_folder_node, | 66 BookmarkNode* other_folder_node, |
| 116 int64* max_id, | 67 int64* max_id, |
| 117 const Value& value) { | 68 const Value& value) { |
| 118 // TODO(munjal): Instead of paying the price of ID generator in al lcases, we | |
| 119 // should only pay the price if we detect the file has changed and do a second | |
| 120 // pass to reassign IDs. See issue 16357. | |
| 121 id_generator_.Reset(); | |
| 122 ids_reassigned_ = false; | 69 ids_reassigned_ = false; |
| 70 ids_missing_ = false; | |
| 71 maximum_id_ = 0; | |
| 123 stored_checksum_.clear(); | 72 stored_checksum_.clear(); |
| 124 InitializeChecksum(); | 73 InitializeChecksum(); |
| 125 bool success = DecodeHelper(bb_node, other_folder_node, value); | 74 bool success = DecodeHelper(bb_node, other_folder_node, value); |
| 126 FinalizeChecksum(); | 75 FinalizeChecksum(); |
| 127 *max_id = id_generator_.current_max() + 1; | 76 // If either the checksums differ or some IDs were missing, reassign IDs. |
| 77 if (ids_missing_ || computed_checksum() != stored_checksum()) | |
| 78 ReassignIDs(bb_node, other_folder_node); | |
| 79 *max_id = maximum_id_ + 1; | |
| 128 return success; | 80 return success; |
| 129 } | 81 } |
| 130 | 82 |
| 131 Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { | 83 Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { |
| 132 DictionaryValue* value = new DictionaryValue(); | 84 DictionaryValue* value = new DictionaryValue(); |
| 133 std::string id; | 85 std::string id; |
| 134 id = Int64ToString(node->id()); | 86 id = Int64ToString(node->id()); |
| 135 value->SetString(kIdKey, id); | 87 value->SetString(kIdKey, id); |
| 136 const std::wstring& title = node->GetTitle(); | 88 const std::wstring& title = node->GetTitle(); |
| 137 value->SetString(kNameKey, title); | 89 value->SetString(kNameKey, title); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 DecodeNode(*static_cast<DictionaryValue*>(child_value), parent, NULL); | 175 DecodeNode(*static_cast<DictionaryValue*>(child_value), parent, NULL); |
| 224 } | 176 } |
| 225 return true; | 177 return true; |
| 226 } | 178 } |
| 227 | 179 |
| 228 bool BookmarkCodec::DecodeNode(const DictionaryValue& value, | 180 bool BookmarkCodec::DecodeNode(const DictionaryValue& value, |
| 229 BookmarkNode* parent, | 181 BookmarkNode* parent, |
| 230 BookmarkNode* node) { | 182 BookmarkNode* node) { |
| 231 std::string id_string; | 183 std::string id_string; |
| 232 int64 id = 0; | 184 int64 id = 0; |
| 233 if (value.GetString(kIdKey, &id_string)) | 185 if (!value.GetString(kIdKey, &id_string) || !StringToInt64(id_string, &id)) |
| 234 if (!StringToInt64(id_string, &id)) | 186 ids_missing_ = true; |
| 235 return false; | 187 |
| 236 int64 new_id = id_generator_.GetUniqueID(id); | 188 maximum_id_ = std::max(maximum_id_, id); |
| 237 if (new_id != id) | |
| 238 ids_reassigned_ = true; | |
| 239 id = new_id; | |
| 240 | 189 |
| 241 std::wstring title; | 190 std::wstring title; |
| 242 if (!value.GetString(kNameKey, &title)) | 191 value.GetString(kNameKey, &title); |
| 243 title = std::wstring(); | |
| 244 | 192 |
| 245 std::wstring date_added_string; | 193 std::wstring date_added_string; |
| 246 if (!value.GetString(kDateAddedKey, &date_added_string)) | 194 if (!value.GetString(kDateAddedKey, &date_added_string)) |
| 247 date_added_string = Int64ToWString(Time::Now().ToInternalValue()); | 195 date_added_string = Int64ToWString(Time::Now().ToInternalValue()); |
| 248 | 196 |
| 249 std::wstring type_string; | 197 std::wstring type_string; |
| 250 if (!value.GetString(kTypeKey, &type_string)) | 198 if (!value.GetString(kTypeKey, &type_string)) |
| 251 return false; | 199 return false; |
| 252 | 200 |
| 253 if (type_string != kTypeURL && type_string != kTypeFolder) | 201 if (type_string != kTypeURL && type_string != kTypeFolder) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 276 if (!value.Get(kChildrenKey, &child_values)) | 224 if (!value.Get(kChildrenKey, &child_values)) |
| 277 return false; | 225 return false; |
| 278 | 226 |
| 279 if (child_values->GetType() != Value::TYPE_LIST) | 227 if (child_values->GetType() != Value::TYPE_LIST) |
| 280 return false; | 228 return false; |
| 281 | 229 |
| 282 if (!node) { | 230 if (!node) { |
| 283 node = new BookmarkNode(id, GURL()); | 231 node = new BookmarkNode(id, GURL()); |
| 284 } else { | 232 } else { |
| 285 // If a new node is not created, explicitly assign ID to the existing one. | 233 // If a new node is not created, explicitly assign ID to the existing one. |
| 286 DCHECK(id != 0); | |
| 287 node->set_id(id); | 234 node->set_id(id); |
| 288 } | 235 } |
| 289 | 236 |
| 290 node->SetType(BookmarkNode::FOLDER); | 237 node->SetType(BookmarkNode::FOLDER); |
| 291 node->set_date_group_modified(Time::FromInternalValue( | 238 node->set_date_group_modified(Time::FromInternalValue( |
| 292 StringToInt64(WideToUTF16Hack(last_modified_date)))); | 239 StringToInt64(WideToUTF16Hack(last_modified_date)))); |
| 293 | 240 |
| 294 if (parent) | 241 if (parent) |
| 295 parent->Add(parent->GetChildCount(), node); | 242 parent->Add(parent->GetChildCount(), node); |
| 296 | 243 |
| 297 UpdateChecksumWithFolderNode(id_string, title); | 244 UpdateChecksumWithFolderNode(id_string, title); |
| 298 | 245 |
| 299 if (!DecodeChildren(*static_cast<ListValue*>(child_values), node)) | 246 if (!DecodeChildren(*static_cast<ListValue*>(child_values), node)) |
| 300 return false; | 247 return false; |
| 301 } | 248 } |
| 302 | 249 |
| 303 node->SetTitle(title); | 250 node->SetTitle(title); |
| 304 node->set_date_added(Time::FromInternalValue( | 251 node->set_date_added(Time::FromInternalValue( |
| 305 StringToInt64(WideToUTF16Hack(date_added_string)))); | 252 StringToInt64(WideToUTF16Hack(date_added_string)))); |
| 306 return true; | 253 return true; |
| 307 } | 254 } |
| 308 | 255 |
| 256 void BookmarkCodec::ReassignIDs(BookmarkNode* bb_node, | |
| 257 BookmarkNode* other_node) { | |
| 258 maximum_id_ = 0; | |
| 259 ReassignIDsHelper(bb_node); | |
|
Erik does not do reviews
2009/07/15 19:44:52
Are there (or should there be) any assumptions abo
| |
| 260 ReassignIDsHelper(other_node); | |
| 261 ids_reassigned_ = true; | |
| 262 } | |
| 263 | |
| 264 void BookmarkCodec::ReassignIDsHelper(BookmarkNode* node) { | |
| 265 DCHECK(node); | |
| 266 node->set_id(++maximum_id_); | |
| 267 for (int i = 0; i < node->GetChildCount(); ++i) | |
| 268 ReassignIDsHelper(node->GetChild(i)); | |
| 269 } | |
| 270 | |
| 309 void BookmarkCodec::UpdateChecksum(const std::string& str) { | 271 void BookmarkCodec::UpdateChecksum(const std::string& str) { |
| 310 MD5Update(&md5_context_, str.data(), str.length() * sizeof(char)); | 272 MD5Update(&md5_context_, str.data(), str.length() * sizeof(char)); |
| 311 } | 273 } |
| 312 | 274 |
| 313 void BookmarkCodec::UpdateChecksum(const std::wstring& str) { | 275 void BookmarkCodec::UpdateChecksum(const std::wstring& str) { |
| 314 MD5Update(&md5_context_, str.data(), str.length() * sizeof(wchar_t)); | 276 MD5Update(&md5_context_, str.data(), str.length() * sizeof(wchar_t)); |
| 315 } | 277 } |
| 316 | 278 |
| 317 void BookmarkCodec::UpdateChecksumWithUrlNode(const std::string& id, | 279 void BookmarkCodec::UpdateChecksumWithUrlNode(const std::string& id, |
| 318 const std::wstring& title, | 280 const std::wstring& title, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 332 | 294 |
| 333 void BookmarkCodec::InitializeChecksum() { | 295 void BookmarkCodec::InitializeChecksum() { |
| 334 MD5Init(&md5_context_); | 296 MD5Init(&md5_context_); |
| 335 } | 297 } |
| 336 | 298 |
| 337 void BookmarkCodec::FinalizeChecksum() { | 299 void BookmarkCodec::FinalizeChecksum() { |
| 338 MD5Digest digest; | 300 MD5Digest digest; |
| 339 MD5Final(&digest, &md5_context_); | 301 MD5Final(&digest, &md5_context_); |
| 340 computed_checksum_ = MD5DigestToBase16(digest); | 302 computed_checksum_ = MD5DigestToBase16(digest); |
| 341 } | 303 } |
| OLD | NEW |