| 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 "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "base/values.h" | 9 #include "base/values.h" |
| 10 #include "chrome/browser/bookmarks/bookmark_model.h" | 10 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 11 #include "googleurl/src/gurl.h" | 11 #include "googleurl/src/gurl.h" |
| 12 #include "grit/generated_resources.h" | 12 #include "grit/generated_resources.h" |
| 13 | 13 |
| 14 using base::Time; | 14 using base::Time; |
| 15 | 15 |
| 16 UniqueIDGenerator::UniqueIDGenerator() { | 16 UniqueIDGenerator::UniqueIDGenerator() { |
| 17 Reset(); | 17 Reset(); |
| 18 } | 18 } |
| 19 | 19 |
| 20 int UniqueIDGenerator::GetUniqueID(int id) { | 20 int64 UniqueIDGenerator::GetUniqueID(int64 id) { |
| 21 // If the given ID is already assigned, generate new ID. | 21 // If the given ID is already assigned, generate new ID. |
| 22 if (IsIdAssigned(id)) | 22 if (IsIdAssigned(id)) |
| 23 id = current_max_ + 1; | 23 id = current_max_ + 1; |
| 24 | 24 |
| 25 // Record the new ID as assigned. | 25 // Record the new ID as assigned. |
| 26 RecordId(id); | 26 RecordId(id); |
| 27 | 27 |
| 28 if (id > current_max_) | 28 if (id > current_max_) |
| 29 current_max_ = id; | 29 current_max_ = id; |
| 30 | 30 |
| 31 return id; | 31 return id; |
| 32 } | 32 } |
| 33 | 33 |
| 34 bool UniqueIDGenerator::IsIdAssigned(int id) const { | 34 bool UniqueIDGenerator::IsIdAssigned(int64 id) const { |
| 35 // If the set is already instantiated, then use the set to determine if the | 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 | 36 // given ID is assigned. Otherwise use the current maximum to determine if the |
| 37 // given ID is assigned. | 37 // given ID is assigned. |
| 38 if (assigned_ids_.get()) | 38 if (assigned_ids_.get()) |
| 39 return assigned_ids_->find(id) != assigned_ids_->end(); | 39 return assigned_ids_->find(id) != assigned_ids_->end(); |
| 40 else | 40 else |
| 41 return id <= current_max_; | 41 return id <= current_max_; |
| 42 } | 42 } |
| 43 | 43 |
| 44 void UniqueIDGenerator::RecordId(int id) { | 44 void UniqueIDGenerator::RecordId(int64 id) { |
| 45 // If the set is instantiated, then use the set. | 45 // If the set is instantiated, then use the set. |
| 46 if (assigned_ids_.get()) { | 46 if (assigned_ids_.get()) { |
| 47 assigned_ids_->insert(id); | 47 assigned_ids_->insert(id); |
| 48 return; | 48 return; |
| 49 } | 49 } |
| 50 | 50 |
| 51 // The set is not yet instantiated. If the ID is current_max_ + 1, then just | 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 | 52 // update the current_max_. Otherwise, instantiate the set and add all IDs |
| 53 // from 0 to current_max_ to it. | 53 // from 0 to current_max_ to it. |
| 54 if (id == current_max_ + 1) { | 54 if (id == current_max_ + 1) { |
| 55 ++current_max_; | 55 ++current_max_; |
| 56 return; | 56 return; |
| 57 } | 57 } |
| 58 assigned_ids_.reset(new std::set<int>); | 58 assigned_ids_.reset(new std::set<int64>); |
| 59 for (int i = 0; i <= current_max_; ++i) | 59 for (int64 i = 0; i <= current_max_; ++i) |
| 60 assigned_ids_->insert(i); | 60 assigned_ids_->insert(i); |
| 61 assigned_ids_->insert(id); | 61 assigned_ids_->insert(id); |
| 62 } | 62 } |
| 63 | 63 |
| 64 void UniqueIDGenerator::Reset() { | 64 void UniqueIDGenerator::Reset() { |
| 65 current_max_ = 0; | 65 current_max_ = 0; |
| 66 assigned_ids_.reset(NULL); | 66 assigned_ids_.reset(NULL); |
| 67 } | 67 } |
| 68 | 68 |
| 69 const wchar_t* BookmarkCodec::kRootsKey = L"roots"; | 69 const wchar_t* BookmarkCodec::kRootsKey = L"roots"; |
| 70 const wchar_t* BookmarkCodec::kRootFolderNameKey = L"bookmark_bar"; | 70 const wchar_t* BookmarkCodec::kRootFolderNameKey = L"bookmark_bar"; |
| 71 const wchar_t* BookmarkCodec::kOtherBookmarkFolderNameKey = L"other"; | 71 const wchar_t* BookmarkCodec::kOtherBookmarkFolderNameKey = L"other"; |
| 72 const wchar_t* BookmarkCodec::kVersionKey = L"version"; | 72 const wchar_t* BookmarkCodec::kVersionKey = L"version"; |
| 73 const wchar_t* BookmarkCodec::kChecksumKey = L"checksum"; | 73 const wchar_t* BookmarkCodec::kChecksumKey = L"checksum"; |
| 74 const wchar_t* BookmarkCodec::kIdKey = L"id"; | 74 const wchar_t* BookmarkCodec::kIdKey = L"id"; |
| 75 const wchar_t* BookmarkCodec::kTypeKey = L"type"; | 75 const wchar_t* BookmarkCodec::kTypeKey = L"type"; |
| 76 const wchar_t* BookmarkCodec::kNameKey = L"name"; | 76 const wchar_t* BookmarkCodec::kNameKey = L"name"; |
| 77 const wchar_t* BookmarkCodec::kDateAddedKey = L"date_added"; | 77 const wchar_t* BookmarkCodec::kDateAddedKey = L"date_added"; |
| 78 const wchar_t* BookmarkCodec::kURLKey = L"url"; | 78 const wchar_t* BookmarkCodec::kURLKey = L"url"; |
| 79 const wchar_t* BookmarkCodec::kDateModifiedKey = L"date_modified"; | 79 const wchar_t* BookmarkCodec::kDateModifiedKey = L"date_modified"; |
| 80 const wchar_t* BookmarkCodec::kChildrenKey = L"children"; | 80 const wchar_t* BookmarkCodec::kChildrenKey = L"children"; |
| 81 const wchar_t* BookmarkCodec::kTypeURL = L"url"; | 81 const wchar_t* BookmarkCodec::kTypeURL = L"url"; |
| 82 const wchar_t* BookmarkCodec::kTypeFolder = L"folder"; | 82 const wchar_t* BookmarkCodec::kTypeFolder = L"folder"; |
| 83 | 83 |
| 84 // Current version of the file. | 84 // Current version of the file. |
| 85 static const int kCurrentVersion = 1; | 85 static const int kCurrentVersion = 1; |
| 86 | 86 |
| 87 BookmarkCodec::BookmarkCodec() | 87 BookmarkCodec::BookmarkCodec() |
| 88 : persist_ids_(false) { | 88 : ids_reassigned_(false) { |
| 89 } | |
| 90 | |
| 91 BookmarkCodec::BookmarkCodec(bool persist_ids) | |
| 92 : persist_ids_(persist_ids) { | |
| 93 } | 89 } |
| 94 | 90 |
| 95 Value* BookmarkCodec::Encode(BookmarkModel* model) { | 91 Value* BookmarkCodec::Encode(BookmarkModel* model) { |
| 96 return Encode(model->GetBookmarkBarNode(), model->other_node()); | 92 return Encode(model->GetBookmarkBarNode(), model->other_node()); |
| 97 } | 93 } |
| 98 | 94 |
| 99 Value* BookmarkCodec::Encode(const BookmarkNode* bookmark_bar_node, | 95 Value* BookmarkCodec::Encode(const BookmarkNode* bookmark_bar_node, |
| 100 const BookmarkNode* other_folder_node) { | 96 const BookmarkNode* other_folder_node) { |
| 97 ids_reassigned_ = false; |
| 101 InitializeChecksum(); | 98 InitializeChecksum(); |
| 102 DictionaryValue* roots = new DictionaryValue(); | 99 DictionaryValue* roots = new DictionaryValue(); |
| 103 roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); | 100 roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); |
| 104 roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); | 101 roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); |
| 105 | 102 |
| 106 DictionaryValue* main = new DictionaryValue(); | 103 DictionaryValue* main = new DictionaryValue(); |
| 107 main->SetInteger(kVersionKey, kCurrentVersion); | 104 main->SetInteger(kVersionKey, kCurrentVersion); |
| 108 FinalizeChecksum(); | 105 FinalizeChecksum(); |
| 109 // We are going to store the computed checksum. So set stored checksum to be | 106 // We are going to store the computed checksum. So set stored checksum to be |
| 110 // the same as computed checksum. | 107 // the same as computed checksum. |
| 111 stored_checksum_ = computed_checksum_; | 108 stored_checksum_ = computed_checksum_; |
| 112 main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_)); | 109 main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_)); |
| 113 main->Set(kRootsKey, roots); | 110 main->Set(kRootsKey, roots); |
| 114 return main; | 111 return main; |
| 115 } | 112 } |
| 116 | 113 |
| 117 bool BookmarkCodec::Decode(BookmarkNode* bb_node, | 114 bool BookmarkCodec::Decode(BookmarkNode* bb_node, |
| 118 BookmarkNode* other_folder_node, | 115 BookmarkNode* other_folder_node, |
| 119 int* max_id, | 116 int64* max_id, |
| 120 const Value& value) { | 117 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(); | 121 id_generator_.Reset(); |
| 122 ids_reassigned_ = false; |
| 122 stored_checksum_.clear(); | 123 stored_checksum_.clear(); |
| 123 InitializeChecksum(); | 124 InitializeChecksum(); |
| 124 bool success = DecodeHelper(bb_node, other_folder_node, max_id, value); | 125 bool success = DecodeHelper(bb_node, other_folder_node, value); |
| 125 FinalizeChecksum(); | 126 FinalizeChecksum(); |
| 126 *max_id = id_generator_.current_max() + 1; | 127 *max_id = id_generator_.current_max() + 1; |
| 127 return success; | 128 return success; |
| 128 } | 129 } |
| 129 | 130 |
| 130 Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { | 131 Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { |
| 131 DictionaryValue* value = new DictionaryValue(); | 132 DictionaryValue* value = new DictionaryValue(); |
| 132 std::string id; | 133 std::string id; |
| 133 if (persist_ids_) { | 134 id = Int64ToString(node->id()); |
| 134 id = IntToString(node->id()); | 135 value->SetString(kIdKey, id); |
| 135 value->SetString(kIdKey, id); | |
| 136 } | |
| 137 const std::wstring& title = node->GetTitle(); | 136 const std::wstring& title = node->GetTitle(); |
| 138 value->SetString(kNameKey, title); | 137 value->SetString(kNameKey, title); |
| 139 value->SetString(kDateAddedKey, | 138 value->SetString(kDateAddedKey, |
| 140 Int64ToWString(node->date_added().ToInternalValue())); | 139 Int64ToWString(node->date_added().ToInternalValue())); |
| 141 if (node->GetType() == BookmarkNode::URL) { | 140 if (node->GetType() == BookmarkNode::URL) { |
| 142 value->SetString(kTypeKey, kTypeURL); | 141 value->SetString(kTypeKey, kTypeURL); |
| 143 std::wstring url = UTF8ToWide(node->GetURL().possibly_invalid_spec()); | 142 std::wstring url = UTF8ToWide(node->GetURL().possibly_invalid_spec()); |
| 144 value->SetString(kURLKey, url); | 143 value->SetString(kURLKey, url); |
| 145 UpdateChecksumWithUrlNode(id, title, url); | 144 UpdateChecksumWithUrlNode(id, title, url); |
| 146 } else { | 145 } else { |
| 147 value->SetString(kTypeKey, kTypeFolder); | 146 value->SetString(kTypeKey, kTypeFolder); |
| 148 value->SetString(kDateModifiedKey, | 147 value->SetString(kDateModifiedKey, |
| 149 Int64ToWString(node->date_group_modified(). | 148 Int64ToWString(node->date_group_modified(). |
| 150 ToInternalValue())); | 149 ToInternalValue())); |
| 151 UpdateChecksumWithFolderNode(id, title); | 150 UpdateChecksumWithFolderNode(id, title); |
| 152 | 151 |
| 153 ListValue* child_values = new ListValue(); | 152 ListValue* child_values = new ListValue(); |
| 154 value->Set(kChildrenKey, child_values); | 153 value->Set(kChildrenKey, child_values); |
| 155 for (int i = 0; i < node->GetChildCount(); ++i) | 154 for (int i = 0; i < node->GetChildCount(); ++i) |
| 156 child_values->Append(EncodeNode(node->GetChild(i))); | 155 child_values->Append(EncodeNode(node->GetChild(i))); |
| 157 } | 156 } |
| 158 return value; | 157 return value; |
| 159 } | 158 } |
| 160 | 159 |
| 161 bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, | 160 bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, |
| 162 BookmarkNode* other_folder_node, | 161 BookmarkNode* other_folder_node, |
| 163 int* max_id, | |
| 164 const Value& value) { | 162 const Value& value) { |
| 165 if (value.GetType() != Value::TYPE_DICTIONARY) | 163 if (value.GetType() != Value::TYPE_DICTIONARY) |
| 166 return false; // Unexpected type. | 164 return false; // Unexpected type. |
| 167 | 165 |
| 168 const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value); | 166 const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value); |
| 169 | 167 |
| 170 int version; | 168 int version; |
| 171 if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) | 169 if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) |
| 172 return false; // Unknown version. | 170 return false; // Unknown version. |
| 173 | 171 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 | 222 |
| 225 DecodeNode(*static_cast<DictionaryValue*>(child_value), parent, NULL); | 223 DecodeNode(*static_cast<DictionaryValue*>(child_value), parent, NULL); |
| 226 } | 224 } |
| 227 return true; | 225 return true; |
| 228 } | 226 } |
| 229 | 227 |
| 230 bool BookmarkCodec::DecodeNode(const DictionaryValue& value, | 228 bool BookmarkCodec::DecodeNode(const DictionaryValue& value, |
| 231 BookmarkNode* parent, | 229 BookmarkNode* parent, |
| 232 BookmarkNode* node) { | 230 BookmarkNode* node) { |
| 233 std::string id_string; | 231 std::string id_string; |
| 234 int id = 0; | 232 int64 id = 0; |
| 235 if (persist_ids_) { | 233 if (value.GetString(kIdKey, &id_string)) |
| 236 if (value.GetString(kIdKey, &id_string)) | 234 if (!StringToInt64(id_string, &id)) |
| 237 if (!StringToInt(id_string, &id)) | 235 return false; |
| 238 return false; | 236 int64 new_id = id_generator_.GetUniqueID(id); |
| 239 } | 237 if (new_id != id) |
| 240 id = id_generator_.GetUniqueID(id); | 238 ids_reassigned_ = true; |
| 239 id = new_id; |
| 241 | 240 |
| 242 std::wstring title; | 241 std::wstring title; |
| 243 if (!value.GetString(kNameKey, &title)) | 242 if (!value.GetString(kNameKey, &title)) |
| 244 title = std::wstring(); | 243 title = std::wstring(); |
| 245 | 244 |
| 246 std::wstring date_added_string; | 245 std::wstring date_added_string; |
| 247 if (!value.GetString(kDateAddedKey, &date_added_string)) | 246 if (!value.GetString(kDateAddedKey, &date_added_string)) |
| 248 date_added_string = Int64ToWString(Time::Now().ToInternalValue()); | 247 date_added_string = Int64ToWString(Time::Now().ToInternalValue()); |
| 249 | 248 |
| 250 std::wstring type_string; | 249 std::wstring type_string; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 | 332 |
| 334 void BookmarkCodec::InitializeChecksum() { | 333 void BookmarkCodec::InitializeChecksum() { |
| 335 MD5Init(&md5_context_); | 334 MD5Init(&md5_context_); |
| 336 } | 335 } |
| 337 | 336 |
| 338 void BookmarkCodec::FinalizeChecksum() { | 337 void BookmarkCodec::FinalizeChecksum() { |
| 339 MD5Digest digest; | 338 MD5Digest digest; |
| 340 MD5Final(&digest, &md5_context_); | 339 MD5Final(&digest, &md5_context_); |
| 341 computed_checksum_ = MD5DigestToBase16(digest); | 340 computed_checksum_ = MD5DigestToBase16(digest); |
| 342 } | 341 } |
| OLD | NEW |