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 const char* BookmarkCodec::kVersionKey = "version"; | 23 const char* BookmarkCodec::kVersionKey = "version"; |
23 const char* BookmarkCodec::kChecksumKey = "checksum"; | 24 const char* BookmarkCodec::kChecksumKey = "checksum"; |
24 const char* BookmarkCodec::kIdKey = "id"; | 25 const char* BookmarkCodec::kIdKey = "id"; |
25 const char* BookmarkCodec::kTypeKey = "type"; | 26 const char* BookmarkCodec::kTypeKey = "type"; |
26 const char* BookmarkCodec::kNameKey = "name"; | 27 const char* BookmarkCodec::kNameKey = "name"; |
27 const char* BookmarkCodec::kDateAddedKey = "date_added"; | 28 const char* BookmarkCodec::kDateAddedKey = "date_added"; |
28 const char* BookmarkCodec::kURLKey = "url"; | 29 const char* BookmarkCodec::kURLKey = "url"; |
29 const char* BookmarkCodec::kDateModifiedKey = "date_modified"; | 30 const char* BookmarkCodec::kDateModifiedKey = "date_modified"; |
30 const char* BookmarkCodec::kChildrenKey = "children"; | 31 const char* BookmarkCodec::kChildrenKey = "children"; |
31 const char* BookmarkCodec::kTypeURL = "url"; | 32 const char* BookmarkCodec::kTypeURL = "url"; |
32 const char* BookmarkCodec::kTypeFolder = "folder"; | 33 const char* BookmarkCodec::kTypeFolder = "folder"; |
33 | 34 |
34 // Current version of the file. | 35 // Current version of the file. |
35 static const int kCurrentVersion = 1; | 36 static const int kCurrentVersion = 1; |
36 | 37 |
37 BookmarkCodec::BookmarkCodec() | 38 BookmarkCodec::BookmarkCodec() |
38 : ids_reassigned_(false), | 39 : ids_reassigned_(false), |
39 ids_valid_(true), | 40 ids_valid_(true), |
40 maximum_id_(0) { | 41 maximum_id_(0) { |
41 } | 42 } |
42 | 43 |
43 BookmarkCodec::~BookmarkCodec() {} | 44 BookmarkCodec::~BookmarkCodec() {} |
44 | 45 |
45 Value* BookmarkCodec::Encode(BookmarkModel* model) { | 46 Value* BookmarkCodec::Encode(BookmarkModel* model) { |
46 return Encode(model->GetBookmarkBarNode(), model->other_node()); | 47 return Encode(model->GetBookmarkBarNode(), model->other_node(), |
| 48 model->synced_node()); |
47 } | 49 } |
48 | 50 |
49 Value* BookmarkCodec::Encode(const BookmarkNode* bookmark_bar_node, | 51 Value* BookmarkCodec::Encode(const BookmarkNode* bookmark_bar_node, |
50 const BookmarkNode* other_folder_node) { | 52 const BookmarkNode* other_folder_node, |
| 53 const BookmarkNode* synced_folder_node) { |
51 ids_reassigned_ = false; | 54 ids_reassigned_ = false; |
52 InitializeChecksum(); | 55 InitializeChecksum(); |
53 DictionaryValue* roots = new DictionaryValue(); | 56 DictionaryValue* roots = new DictionaryValue(); |
54 roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); | 57 roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node)); |
55 roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); | 58 roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node)); |
| 59 roots->Set(kSyncedBookmarkFolderNameKey, EncodeNode(synced_folder_node)); |
56 | 60 |
57 DictionaryValue* main = new DictionaryValue(); | 61 DictionaryValue* main = new DictionaryValue(); |
58 main->SetInteger(kVersionKey, kCurrentVersion); | 62 main->SetInteger(kVersionKey, kCurrentVersion); |
59 FinalizeChecksum(); | 63 FinalizeChecksum(); |
60 // We are going to store the computed checksum. So set stored checksum to be | 64 // We are going to store the computed checksum. So set stored checksum to be |
61 // the same as computed checksum. | 65 // the same as computed checksum. |
62 stored_checksum_ = computed_checksum_; | 66 stored_checksum_ = computed_checksum_; |
63 main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_)); | 67 main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_)); |
64 main->Set(kRootsKey, roots); | 68 main->Set(kRootsKey, roots); |
65 return main; | 69 return main; |
66 } | 70 } |
67 | 71 |
68 bool BookmarkCodec::Decode(BookmarkNode* bb_node, | 72 bool BookmarkCodec::Decode(BookmarkNode* bb_node, |
69 BookmarkNode* other_folder_node, | 73 BookmarkNode* other_folder_node, |
| 74 BookmarkNode* synced_folder_node, |
70 int64* max_id, | 75 int64* max_id, |
71 const Value& value) { | 76 const Value& value) { |
72 ids_.clear(); | 77 ids_.clear(); |
73 ids_reassigned_ = false; | 78 ids_reassigned_ = false; |
74 ids_valid_ = true; | 79 ids_valid_ = true; |
75 maximum_id_ = 0; | 80 maximum_id_ = 0; |
76 stored_checksum_.clear(); | 81 stored_checksum_.clear(); |
77 InitializeChecksum(); | 82 InitializeChecksum(); |
78 bool success = DecodeHelper(bb_node, other_folder_node, value); | 83 bool success = DecodeHelper(bb_node, other_folder_node, synced_folder_node, |
| 84 value); |
79 FinalizeChecksum(); | 85 FinalizeChecksum(); |
80 // If either the checksums differ or some IDs were missing/not unique, | 86 // If either the checksums differ or some IDs were missing/not unique, |
81 // reassign IDs. | 87 // reassign IDs. |
82 if (!ids_valid_ || computed_checksum() != stored_checksum()) | 88 if (!ids_valid_ || computed_checksum() != stored_checksum()) |
83 ReassignIDs(bb_node, other_folder_node); | 89 ReassignIDs(bb_node, other_folder_node, synced_folder_node); |
84 *max_id = maximum_id_ + 1; | 90 *max_id = maximum_id_ + 1; |
85 return success; | 91 return success; |
86 } | 92 } |
87 | 93 |
88 Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { | 94 Value* BookmarkCodec::EncodeNode(const BookmarkNode* node) { |
89 DictionaryValue* value = new DictionaryValue(); | 95 DictionaryValue* value = new DictionaryValue(); |
90 std::string id = base::Int64ToString(node->id()); | 96 std::string id = base::Int64ToString(node->id()); |
91 value->SetString(kIdKey, id); | 97 value->SetString(kIdKey, id); |
92 const string16& title = node->GetTitle(); | 98 const string16& title = node->GetTitle(); |
93 value->SetString(kNameKey, title); | 99 value->SetString(kNameKey, title); |
(...skipping 14 matching lines...) Expand all Loading... |
108 ListValue* child_values = new ListValue(); | 114 ListValue* child_values = new ListValue(); |
109 value->Set(kChildrenKey, child_values); | 115 value->Set(kChildrenKey, child_values); |
110 for (int i = 0; i < node->child_count(); ++i) | 116 for (int i = 0; i < node->child_count(); ++i) |
111 child_values->Append(EncodeNode(node->GetChild(i))); | 117 child_values->Append(EncodeNode(node->GetChild(i))); |
112 } | 118 } |
113 return value; | 119 return value; |
114 } | 120 } |
115 | 121 |
116 bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, | 122 bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node, |
117 BookmarkNode* other_folder_node, | 123 BookmarkNode* other_folder_node, |
| 124 BookmarkNode* synced_folder_node, |
118 const Value& value) { | 125 const Value& value) { |
119 if (value.GetType() != Value::TYPE_DICTIONARY) | 126 if (value.GetType() != Value::TYPE_DICTIONARY) |
120 return false; // Unexpected type. | 127 return false; // Unexpected type. |
121 | 128 |
122 const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value); | 129 const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value); |
123 | 130 |
124 int version; | 131 int version; |
125 if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) | 132 if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion) |
126 return false; // Unknown version. | 133 return false; // Unknown version. |
127 | 134 |
(...skipping 12 matching lines...) Expand all Loading... |
140 | 147 |
141 if (roots->GetType() != Value::TYPE_DICTIONARY) | 148 if (roots->GetType() != Value::TYPE_DICTIONARY) |
142 return false; // Invalid type for roots. | 149 return false; // Invalid type for roots. |
143 | 150 |
144 DictionaryValue* roots_d_value = static_cast<DictionaryValue*>(roots); | 151 DictionaryValue* roots_d_value = static_cast<DictionaryValue*>(roots); |
145 Value* root_folder_value; | 152 Value* root_folder_value; |
146 Value* other_folder_value; | 153 Value* other_folder_value; |
147 if (!roots_d_value->Get(kRootFolderNameKey, &root_folder_value) || | 154 if (!roots_d_value->Get(kRootFolderNameKey, &root_folder_value) || |
148 root_folder_value->GetType() != Value::TYPE_DICTIONARY || | 155 root_folder_value->GetType() != Value::TYPE_DICTIONARY || |
149 !roots_d_value->Get(kOtherBookmarkFolderNameKey, &other_folder_value) || | 156 !roots_d_value->Get(kOtherBookmarkFolderNameKey, &other_folder_value) || |
150 other_folder_value->GetType() != Value::TYPE_DICTIONARY) | 157 other_folder_value->GetType() != Value::TYPE_DICTIONARY) { |
151 return false; // Invalid type for root folder and/or other folder. | 158 return false; // Invalid type for root folder and/or other |
152 | 159 // folder. |
| 160 } |
153 DecodeNode(*static_cast<DictionaryValue*>(root_folder_value), NULL, | 161 DecodeNode(*static_cast<DictionaryValue*>(root_folder_value), NULL, |
154 bb_node); | 162 bb_node); |
155 DecodeNode(*static_cast<DictionaryValue*>(other_folder_value), NULL, | 163 DecodeNode(*static_cast<DictionaryValue*>(other_folder_value), NULL, |
156 other_folder_node); | 164 other_folder_node); |
| 165 |
| 166 // Fail silently if we can't deserialize synced bookmarks. We can't require |
| 167 // them to exist in order to be backwards-compatible with older versions of |
| 168 // chrome. |
| 169 Value* synced_folder_value; |
| 170 if (roots_d_value->Get(kSyncedBookmarkFolderNameKey, &synced_folder_value) && |
| 171 synced_folder_value->GetType() == Value::TYPE_DICTIONARY) { |
| 172 DecodeNode(*static_cast<DictionaryValue*>(synced_folder_value), NULL, |
| 173 synced_folder_node); |
| 174 } else { |
| 175 // If we didn't find the synced folder, we're almost guaranteed to have a |
| 176 // duplicate id when we add the synced folder. Consequently, if we don't |
| 177 // intend to reassign ids in the future (ids_valid_ is still true), then at |
| 178 // least reassign the synced bookmarks to avoid it colliding with anything |
| 179 // else. |
| 180 if (ids_valid_) { |
| 181 ReassignIDsHelper(synced_folder_node); |
| 182 } |
| 183 } |
| 184 |
157 // Need to reset the type as decoding resets the type to FOLDER. Similarly | 185 // Need to reset the type as decoding resets the type to FOLDER. Similarly |
158 // we need to reset the title as the title is persisted and restored from | 186 // we need to reset the title as the title is persisted and restored from |
159 // the file. | 187 // the file. |
160 bb_node->set_type(BookmarkNode::BOOKMARK_BAR); | 188 bb_node->set_type(BookmarkNode::BOOKMARK_BAR); |
161 other_folder_node->set_type(BookmarkNode::OTHER_NODE); | 189 other_folder_node->set_type(BookmarkNode::OTHER_NODE); |
| 190 synced_folder_node->set_type(BookmarkNode::SYNCED); |
162 bb_node->set_title(l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_FOLDER_NAME)); | 191 bb_node->set_title(l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_FOLDER_NAME)); |
163 other_folder_node->set_title( | 192 other_folder_node->set_title( |
164 l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_OTHER_FOLDER_NAME)); | 193 l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_OTHER_FOLDER_NAME)); |
| 194 synced_folder_node->set_title( |
| 195 l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_SYNCED_FOLDER_NAME)); |
165 | 196 |
166 return true; | 197 return true; |
167 } | 198 } |
168 | 199 |
169 bool BookmarkCodec::DecodeChildren(const ListValue& child_value_list, | 200 bool BookmarkCodec::DecodeChildren(const ListValue& child_value_list, |
170 BookmarkNode* parent) { | 201 BookmarkNode* parent) { |
171 for (size_t i = 0; i < child_value_list.GetSize(); ++i) { | 202 for (size_t i = 0; i < child_value_list.GetSize(); ++i) { |
172 Value* child_value; | 203 Value* child_value; |
173 if (!child_value_list.Get(i, &child_value)) | 204 if (!child_value_list.Get(i, &child_value)) |
174 return false; | 205 return false; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 if (!DecodeChildren(*static_cast<ListValue*>(child_values), node)) | 313 if (!DecodeChildren(*static_cast<ListValue*>(child_values), node)) |
283 return false; | 314 return false; |
284 } | 315 } |
285 | 316 |
286 node->set_title(title); | 317 node->set_title(title); |
287 node->set_date_added(date_added); | 318 node->set_date_added(date_added); |
288 return true; | 319 return true; |
289 } | 320 } |
290 | 321 |
291 void BookmarkCodec::ReassignIDs(BookmarkNode* bb_node, | 322 void BookmarkCodec::ReassignIDs(BookmarkNode* bb_node, |
292 BookmarkNode* other_node) { | 323 BookmarkNode* other_node, |
| 324 BookmarkNode* synced_node) { |
293 maximum_id_ = 0; | 325 maximum_id_ = 0; |
294 ReassignIDsHelper(bb_node); | 326 ReassignIDsHelper(bb_node); |
295 ReassignIDsHelper(other_node); | 327 ReassignIDsHelper(other_node); |
| 328 ReassignIDsHelper(synced_node); |
296 ids_reassigned_ = true; | 329 ids_reassigned_ = true; |
297 } | 330 } |
298 | 331 |
299 void BookmarkCodec::ReassignIDsHelper(BookmarkNode* node) { | 332 void BookmarkCodec::ReassignIDsHelper(BookmarkNode* node) { |
300 DCHECK(node); | 333 DCHECK(node); |
301 node->set_id(++maximum_id_); | 334 node->set_id(++maximum_id_); |
302 for (int i = 0; i < node->child_count(); ++i) | 335 for (int i = 0; i < node->child_count(); ++i) |
303 ReassignIDsHelper(node->GetChild(i)); | 336 ReassignIDsHelper(node->GetChild(i)); |
304 } | 337 } |
305 | 338 |
(...skipping 24 matching lines...) Expand all Loading... |
330 | 363 |
331 void BookmarkCodec::InitializeChecksum() { | 364 void BookmarkCodec::InitializeChecksum() { |
332 MD5Init(&md5_context_); | 365 MD5Init(&md5_context_); |
333 } | 366 } |
334 | 367 |
335 void BookmarkCodec::FinalizeChecksum() { | 368 void BookmarkCodec::FinalizeChecksum() { |
336 MD5Digest digest; | 369 MD5Digest digest; |
337 MD5Final(&digest, &md5_context_); | 370 MD5Final(&digest, &md5_context_); |
338 computed_checksum_ = MD5DigestToBase16(digest); | 371 computed_checksum_ = MD5DigestToBase16(digest); |
339 } | 372 } |
OLD | NEW |