| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 11 #include "base/values.h" | 11 #include "base/values.h" |
| 12 #include "chrome/browser/bookmarks/bookmark_model.h" | 12 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 13 #include "googleurl/src/gurl.h" | 13 #include "googleurl/src/gurl.h" |
| 14 #include "grit/generated_resources.h" | 14 #include "grit/generated_resources.h" |
| 15 #include "ui/base/l10n/l10n_util.h" | 15 #include "ui/base/l10n/l10n_util.h" |
| 16 | 16 |
| 17 using base::Time; | 17 using base::Time; |
| 18 | 18 |
| 19 const char* BookmarkCodec::kRootsKey = "roots"; | 19 const char* BookmarkCodec::kRootsKey = "roots"; |
| 20 const char* BookmarkCodec::kRootFolderNameKey = "bookmark_bar"; | 20 const char* BookmarkCodec::kRootFolderNameKey = "bookmark_bar"; |
| 21 const char* BookmarkCodec::kOtherBookmarkFolderNameKey = "other"; | 21 const char* BookmarkCodec::kOtherBookmarkFolderNameKey = "other"; |
| 22 const char* BookmarkCodec::kSyncedBookmarkFolderNameKey = "synced"; | 22 // The value is left as 'synced' for historical reasons. |
| 23 const char* BookmarkCodec::kMobileBookmarkFolderNameKey = "synced"; |
| 23 const char* BookmarkCodec::kVersionKey = "version"; | 24 const char* BookmarkCodec::kVersionKey = "version"; |
| 24 const char* BookmarkCodec::kChecksumKey = "checksum"; | 25 const char* BookmarkCodec::kChecksumKey = "checksum"; |
| 25 const char* BookmarkCodec::kIdKey = "id"; | 26 const char* BookmarkCodec::kIdKey = "id"; |
| 26 const char* BookmarkCodec::kTypeKey = "type"; | 27 const char* BookmarkCodec::kTypeKey = "type"; |
| 27 const char* BookmarkCodec::kNameKey = "name"; | 28 const char* BookmarkCodec::kNameKey = "name"; |
| 28 const char* BookmarkCodec::kDateAddedKey = "date_added"; | 29 const char* BookmarkCodec::kDateAddedKey = "date_added"; |
| 29 const char* BookmarkCodec::kURLKey = "url"; | 30 const char* BookmarkCodec::kURLKey = "url"; |
| 30 const char* BookmarkCodec::kDateModifiedKey = "date_modified"; | 31 const char* BookmarkCodec::kDateModifiedKey = "date_modified"; |
| 31 const char* BookmarkCodec::kChildrenKey = "children"; | 32 const char* BookmarkCodec::kChildrenKey = "children"; |
| 32 const char* BookmarkCodec::kTypeURL = "url"; | 33 const char* BookmarkCodec::kTypeURL = "url"; |
| 33 const char* BookmarkCodec::kTypeFolder = "folder"; | 34 const char* BookmarkCodec::kTypeFolder = "folder"; |
| 34 | 35 |
| 35 // Current version of the file. | 36 // Current version of the file. |
| 36 static const int kCurrentVersion = 1; | 37 static const int kCurrentVersion = 1; |
| 37 | 38 |
| 38 BookmarkCodec::BookmarkCodec() | 39 BookmarkCodec::BookmarkCodec() |
| 39 : ids_reassigned_(false), | 40 : ids_reassigned_(false), |
| 40 ids_valid_(true), | 41 ids_valid_(true), |
| 41 maximum_id_(0) { | 42 maximum_id_(0) { |
| 42 } | 43 } |
| 43 | 44 |
| 44 BookmarkCodec::~BookmarkCodec() {} | 45 BookmarkCodec::~BookmarkCodec() {} |
| 45 | 46 |
| 46 Value* BookmarkCodec::Encode(BookmarkModel* model) { | 47 Value* BookmarkCodec::Encode(BookmarkModel* model) { |
| 47 return Encode(model->bookmark_bar_node(), | 48 return Encode(model->bookmark_bar_node(), |
| 48 model->other_node(), | 49 model->other_node(), |
| 49 model->synced_node()); | 50 model->mobile_node()); |
| 50 } | 51 } |
| 51 | 52 |
| 52 Value* BookmarkCodec::Encode(const BookmarkNode* bookmark_bar_node, | 53 Value* BookmarkCodec::Encode(const BookmarkNode* bookmark_bar_node, |
| 53 const BookmarkNode* other_folder_node, | 54 const BookmarkNode* other_folder_node, |
| 54 const BookmarkNode* synced_folder_node) { | 55 const BookmarkNode* mobile_folder_node) { |
| 55 ids_reassigned_ = false; | 56 ids_reassigned_ = false; |
| 56 InitializeChecksum(); | 57 InitializeChecksum(); |
| 57 DictionaryValue* roots = new DictionaryValue(); | 58 DictionaryValue* roots = new DictionaryValue(); |
| 58 roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); | 59 roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); |
| 59 roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); | 60 roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); |
| 60 roots->Set(kSyncedBookmarkFolderNameKey, EncodeNode(synced_folder_node)); | 61 roots->Set(kMobileBookmarkFolderNameKey, EncodeNode(mobile_folder_node)); |
| 61 | 62 |
| 62 DictionaryValue* main = new DictionaryValue(); | 63 DictionaryValue* main = new DictionaryValue(); |
| 63 main->SetInteger(kVersionKey, kCurrentVersion); | 64 main->SetInteger(kVersionKey, kCurrentVersion); |
| 64 FinalizeChecksum(); | 65 FinalizeChecksum(); |
| 65 // We are going to store the computed checksum. So set stored checksum to be | 66 // We are going to store the computed checksum. So set stored checksum to be |
| 66 // the same as computed checksum. | 67 // the same as computed checksum. |
| 67 stored_checksum_ = computed_checksum_; | 68 stored_checksum_ = computed_checksum_; |
| 68 main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_)); | 69 main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_)); |
| 69 main->Set(kRootsKey, roots); | 70 main->Set(kRootsKey, roots); |
| 70 return main; | 71 return main; |
| 71 } | 72 } |
| 72 | 73 |
| 73 bool BookmarkCodec::Decode(BookmarkNode* bb_node, | 74 bool BookmarkCodec::Decode(BookmarkNode* bb_node, |
| 74 BookmarkNode* other_folder_node, | 75 BookmarkNode* other_folder_node, |
| 75 BookmarkNode* synced_folder_node, | 76 BookmarkNode* mobile_folder_node, |
| 76 int64* max_id, | 77 int64* max_id, |
| 77 const Value& value) { | 78 const Value& value) { |
| 78 ids_.clear(); | 79 ids_.clear(); |
| 79 ids_reassigned_ = false; | 80 ids_reassigned_ = false; |
| 80 ids_valid_ = true; | 81 ids_valid_ = true; |
| 81 maximum_id_ = 0; | 82 maximum_id_ = 0; |
| 82 stored_checksum_.clear(); | 83 stored_checksum_.clear(); |
| 83 InitializeChecksum(); | 84 InitializeChecksum(); |
| 84 bool success = DecodeHelper(bb_node, other_folder_node, synced_folder_node, | 85 bool success = DecodeHelper(bb_node, other_folder_node, mobile_folder_node, |
| 85 value); | 86 value); |
| 86 FinalizeChecksum(); | 87 FinalizeChecksum(); |
| 87 // If either the checksums differ or some IDs were missing/not unique, | 88 // If either the checksums differ or some IDs were missing/not unique, |
| 88 // reassign IDs. | 89 // reassign IDs. |
| 89 if (!ids_valid_ || computed_checksum() != stored_checksum()) | 90 if (!ids_valid_ || computed_checksum() != stored_checksum()) |
| 90 ReassignIDs(bb_node, other_folder_node, synced_folder_node); | 91 ReassignIDs(bb_node, other_folder_node, mobile_folder_node); |
| 91 *max_id = maximum_id_ + 1; | 92 *max_id = maximum_id_ + 1; |
| 92 return success; | 93 return success; |
| 93 } | 94 } |
| 94 | 95 |
| 95 Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { | 96 Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { |
| 96 DictionaryValue* value = new DictionaryValue(); | 97 DictionaryValue* value = new DictionaryValue(); |
| 97 std::string id = base::Int64ToString(node->id()); | 98 std::string id = base::Int64ToString(node->id()); |
| 98 value->SetString(kIdKey, id); | 99 value->SetString(kIdKey, id); |
| 99 const string16& title = node->GetTitle(); | 100 const string16& title = node->GetTitle(); |
| 100 value->SetString(kNameKey, title); | 101 value->SetString(kNameKey, title); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 115 ListValue* child_values = new ListValue(); | 116 ListValue* child_values = new ListValue(); |
| 116 value->Set(kChildrenKey, child_values); | 117 value->Set(kChildrenKey, child_values); |
| 117 for (int i = 0; i < node->child_count(); ++i) | 118 for (int i = 0; i < node->child_count(); ++i) |
| 118 child_values->Append(EncodeNode(node->GetChild(i))); | 119 child_values->Append(EncodeNode(node->GetChild(i))); |
| 119 } | 120 } |
| 120 return value; | 121 return value; |
| 121 } | 122 } |
| 122 | 123 |
| 123 bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, | 124 bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, |
| 124 BookmarkNode* other_folder_node, | 125 BookmarkNode* other_folder_node, |
| 125 BookmarkNode* synced_folder_node, | 126 BookmarkNode* mobile_folder_node, |
| 126 const Value& value) { | 127 const Value& value) { |
| 127 if (value.GetType() != Value::TYPE_DICTIONARY) | 128 if (value.GetType() != Value::TYPE_DICTIONARY) |
| 128 return false; // Unexpected type. | 129 return false; // Unexpected type. |
| 129 | 130 |
| 130 const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value); | 131 const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value); |
| 131 | 132 |
| 132 int version; | 133 int version; |
| 133 if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) | 134 if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) |
| 134 return false; // Unknown version. | 135 return false; // Unknown version. |
| 135 | 136 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 157 !roots_d_value->Get(kOtherBookmarkFolderNameKey, &other_folder_value) || | 158 !roots_d_value->Get(kOtherBookmarkFolderNameKey, &other_folder_value) || |
| 158 other_folder_value->GetType() != Value::TYPE_DICTIONARY) { | 159 other_folder_value->GetType() != Value::TYPE_DICTIONARY) { |
| 159 return false; // Invalid type for root folder and/or other | 160 return false; // Invalid type for root folder and/or other |
| 160 // folder. | 161 // folder. |
| 161 } | 162 } |
| 162 DecodeNode(*static_cast<DictionaryValue*>(root_folder_value), NULL, | 163 DecodeNode(*static_cast<DictionaryValue*>(root_folder_value), NULL, |
| 163 bb_node); | 164 bb_node); |
| 164 DecodeNode(*static_cast<DictionaryValue*>(other_folder_value), NULL, | 165 DecodeNode(*static_cast<DictionaryValue*>(other_folder_value), NULL, |
| 165 other_folder_node); | 166 other_folder_node); |
| 166 | 167 |
| 167 // Fail silently if we can't deserialize synced bookmarks. We can't require | 168 // Fail silently if we can't deserialize mobile bookmarks. We can't require |
| 168 // them to exist in order to be backwards-compatible with older versions of | 169 // them to exist in order to be backwards-compatible with older versions of |
| 169 // chrome. | 170 // chrome. |
| 170 Value* synced_folder_value; | 171 Value* mobile_folder_value; |
| 171 if (roots_d_value->Get(kSyncedBookmarkFolderNameKey, &synced_folder_value) && | 172 if (roots_d_value->Get(kMobileBookmarkFolderNameKey, &mobile_folder_value) && |
| 172 synced_folder_value->GetType() == Value::TYPE_DICTIONARY) { | 173 mobile_folder_value->GetType() == Value::TYPE_DICTIONARY) { |
| 173 DecodeNode(*static_cast<DictionaryValue*>(synced_folder_value), NULL, | 174 DecodeNode(*static_cast<DictionaryValue*>(mobile_folder_value), NULL, |
| 174 synced_folder_node); | 175 mobile_folder_node); |
| 175 } else { | 176 } else { |
| 176 // If we didn't find the synced folder, we're almost guaranteed to have a | 177 // If we didn't find the mobile folder, we're almost guaranteed to have a |
| 177 // duplicate id when we add the synced folder. Consequently, if we don't | 178 // duplicate id when we add the mobile folder. Consequently, if we don't |
| 178 // intend to reassign ids in the future (ids_valid_ is still true), then at | 179 // intend to reassign ids in the future (ids_valid_ is still true), then at |
| 179 // least reassign the synced bookmarks to avoid it colliding with anything | 180 // least reassign the mobile bookmarks to avoid it colliding with anything |
| 180 // else. | 181 // else. |
| 181 if (ids_valid_) { | 182 if (ids_valid_) |
| 182 ReassignIDsHelper(synced_folder_node); | 183 ReassignIDsHelper(mobile_folder_node); |
| 183 } | |
| 184 } | 184 } |
| 185 | 185 |
| 186 // Need to reset the type as decoding resets the type to FOLDER. Similarly | 186 // Need to reset the type as decoding resets the type to FOLDER. Similarly |
| 187 // we need to reset the title as the title is persisted and restored from | 187 // we need to reset the title as the title is persisted and restored from |
| 188 // the file. | 188 // the file. |
| 189 bb_node->set_type(BookmarkNode::BOOKMARK_BAR); | 189 bb_node->set_type(BookmarkNode::BOOKMARK_BAR); |
| 190 other_folder_node->set_type(BookmarkNode::OTHER_NODE); | 190 other_folder_node->set_type(BookmarkNode::OTHER_NODE); |
| 191 synced_folder_node->set_type(BookmarkNode::SYNCED); | 191 mobile_folder_node->set_type(BookmarkNode::MOBILE); |
| 192 bb_node->set_title(l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME)); | 192 bb_node->set_title(l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME)); |
| 193 other_folder_node->set_title( | 193 other_folder_node->set_title( |
| 194 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OTHER_FOLDER_NAME)); | 194 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OTHER_FOLDER_NAME)); |
| 195 synced_folder_node->set_title( | 195 mobile_folder_node->set_title( |
| 196 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_SYNCED_FOLDER_NAME)); | 196 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_MOBILE_FOLDER_NAME)); |
| 197 | 197 |
| 198 return true; | 198 return true; |
| 199 } | 199 } |
| 200 | 200 |
| 201 bool BookmarkCodec::DecodeChildren(const ListValue& child_value_list, | 201 bool BookmarkCodec::DecodeChildren(const ListValue& child_value_list, |
| 202 BookmarkNode* parent) { | 202 BookmarkNode* parent) { |
| 203 for (size_t i = 0; i < child_value_list.GetSize(); ++i) { | 203 for (size_t i = 0; i < child_value_list.GetSize(); ++i) { |
| 204 Value* child_value; | 204 Value* child_value; |
| 205 if (!child_value_list.Get(i, &child_value)) | 205 if (!child_value_list.Get(i, &child_value)) |
| 206 return false; | 206 return false; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 return false; | 315 return false; |
| 316 } | 316 } |
| 317 | 317 |
| 318 node->set_title(title); | 318 node->set_title(title); |
| 319 node->set_date_added(date_added); | 319 node->set_date_added(date_added); |
| 320 return true; | 320 return true; |
| 321 } | 321 } |
| 322 | 322 |
| 323 void BookmarkCodec::ReassignIDs(BookmarkNode* bb_node, | 323 void BookmarkCodec::ReassignIDs(BookmarkNode* bb_node, |
| 324 BookmarkNode* other_node, | 324 BookmarkNode* other_node, |
| 325 BookmarkNode* synced_node) { | 325 BookmarkNode* mobile_node) { |
| 326 maximum_id_ = 0; | 326 maximum_id_ = 0; |
| 327 ReassignIDsHelper(bb_node); | 327 ReassignIDsHelper(bb_node); |
| 328 ReassignIDsHelper(other_node); | 328 ReassignIDsHelper(other_node); |
| 329 ReassignIDsHelper(synced_node); | 329 ReassignIDsHelper(mobile_node); |
| 330 ids_reassigned_ = true; | 330 ids_reassigned_ = true; |
| 331 } | 331 } |
| 332 | 332 |
| 333 void BookmarkCodec::ReassignIDsHelper(BookmarkNode* node) { | 333 void BookmarkCodec::ReassignIDsHelper(BookmarkNode* node) { |
| 334 DCHECK(node); | 334 DCHECK(node); |
| 335 node->set_id(++maximum_id_); | 335 node->set_id(++maximum_id_); |
| 336 for (int i = 0; i < node->child_count(); ++i) | 336 for (int i = 0; i < node->child_count(); ++i) |
| 337 ReassignIDsHelper(node->GetChild(i)); | 337 ReassignIDsHelper(node->GetChild(i)); |
| 338 } | 338 } |
| 339 | 339 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 367 | 367 |
| 368 void BookmarkCodec::InitializeChecksum() { | 368 void BookmarkCodec::InitializeChecksum() { |
| 369 base::MD5Init(&md5_context_); | 369 base::MD5Init(&md5_context_); |
| 370 } | 370 } |
| 371 | 371 |
| 372 void BookmarkCodec::FinalizeChecksum() { | 372 void BookmarkCodec::FinalizeChecksum() { |
| 373 base::MD5Digest digest; | 373 base::MD5Digest digest; |
| 374 base::MD5Final(&digest, &md5_context_); | 374 base::MD5Final(&digest, &md5_context_); |
| 375 computed_checksum_ = base::MD5DigestToBase16(digest); | 375 computed_checksum_ = base::MD5DigestToBase16(digest); |
| 376 } | 376 } |
| OLD | NEW |