bookmark_node.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/bookmarks/browser/bookmark_node.h"
  5. #include <map>
  6. #include <memory>
  7. #include <string>
  8. #include "base/check.h"
  9. #include "base/check_op.h"
  10. #include "base/guid.h"
  11. #include "base/memory/ptr_util.h"
  12. #include "base/strings/string_piece.h"
  13. #include "base/strings/string_util.h"
  14. #include "base/strings/utf_string_conversions.h"
  15. #include "components/strings/grit/components_strings.h"
  16. #include "ui/base/l10n/l10n_util.h"
  17. namespace bookmarks {
  18. namespace {
  19. // Whitespace characters to strip from bookmark titles.
  20. const char16_t kInvalidChars[] = {'\n', '\r', '\t',
  21. 0x2028, // Line separator
  22. 0x2029, // Paragraph separator
  23. 0};
  24. } // namespace
  25. // BookmarkNode ---------------------------------------------------------------
  26. // Below predefined GUIDs for permanent bookmark folders, determined via named
  27. // GUIDs/UUIDs. Do NOT modify them as they may be exposed via Sync. For
  28. // reference, here's the python script to produce them:
  29. // > import uuid
  30. // > chromium_namespace = uuid.uuid5(uuid.NAMESPACE_DNS, "chromium.org")
  31. // > bookmarks_namespace = uuid.uuid5(chromium_namespace, "bookmarks")
  32. // > root_guid = uuid.uuid5(bookmarks_namespace, "root")
  33. // > bookmark_bar = uuid.uuid5(bookmarks_namespace, "bookmark_bar")
  34. // > mobile_bookmarks = uuid.uuid5(bookmarks_namespace, "mobile_bookmarks")
  35. // > other_bookmarks = uuid.uuid5(bookmarks_namespace, "other_bookmarks")
  36. // > managed_bookmarks = uuid.uuid5(bookmarks_namespace, "managed_bookmarks")
  37. // static
  38. const char BookmarkNode::kRootNodeGuid[] =
  39. "2509a7dc-215d-52f7-a429-8d80431c6c75";
  40. // static
  41. const char BookmarkNode::kBookmarkBarNodeGuid[] =
  42. "0bc5d13f-2cba-5d74-951f-3f233fe6c908";
  43. // static
  44. const char BookmarkNode::kOtherBookmarksNodeGuid[] =
  45. "82b081ec-3dd3-529c-8475-ab6c344590dd";
  46. // static
  47. const char BookmarkNode::kMobileBookmarksNodeGuid[] =
  48. "4cf2e351-0e85-532b-bb37-df045d8f8d0f";
  49. // static
  50. const char BookmarkNode::kManagedNodeGuid[] =
  51. "323123f4-9381-5aee-80e6-ea5fca2f7672";
  52. // This value is the result of exercising sync's function
  53. // syncer::InferGuidForLegacyBookmark() with an empty input.
  54. const char BookmarkNode::kBannedGuidDueToPastSyncBug[] =
  55. "da39a3ee-5e6b-fb0d-b255-bfef95601890";
  56. BookmarkNode::BookmarkNode(int64_t id, const base::GUID& guid, const GURL& url)
  57. : BookmarkNode(id, guid, url, url.is_empty() ? FOLDER : URL, false) {}
  58. BookmarkNode::~BookmarkNode() = default;
  59. void BookmarkNode::SetTitle(const std::u16string& title) {
  60. // Replace newlines and other problematic whitespace characters in
  61. // folder/bookmark names with spaces.
  62. std::u16string trimmed_title;
  63. base::ReplaceChars(title, kInvalidChars, u" ", &trimmed_title);
  64. ui::TreeNode<BookmarkNode>::SetTitle(trimmed_title);
  65. }
  66. bool BookmarkNode::IsVisible() const {
  67. return true;
  68. }
  69. bool BookmarkNode::GetMetaInfo(const std::string& key,
  70. std::string* value) const {
  71. if (!meta_info_map_)
  72. return false;
  73. MetaInfoMap::const_iterator it = meta_info_map_->find(key);
  74. if (it == meta_info_map_->end())
  75. return false;
  76. *value = it->second;
  77. return true;
  78. }
  79. bool BookmarkNode::SetMetaInfo(const std::string& key,
  80. const std::string& value) {
  81. if (!meta_info_map_)
  82. meta_info_map_ = std::make_unique<MetaInfoMap>();
  83. auto it = meta_info_map_->find(key);
  84. if (it == meta_info_map_->end()) {
  85. (*meta_info_map_)[key] = value;
  86. return true;
  87. }
  88. // Key already in map, check if the value has changed.
  89. if (it->second == value)
  90. return false;
  91. it->second = value;
  92. return true;
  93. }
  94. bool BookmarkNode::DeleteMetaInfo(const std::string& key) {
  95. if (!meta_info_map_)
  96. return false;
  97. bool erased = meta_info_map_->erase(key) != 0;
  98. if (meta_info_map_->empty())
  99. meta_info_map_.reset();
  100. return erased;
  101. }
  102. void BookmarkNode::SetMetaInfoMap(const MetaInfoMap& meta_info_map) {
  103. if (meta_info_map.empty())
  104. meta_info_map_.reset();
  105. else
  106. meta_info_map_ = std::make_unique<MetaInfoMap>(meta_info_map);
  107. }
  108. const BookmarkNode::MetaInfoMap* BookmarkNode::GetMetaInfoMap() const {
  109. return meta_info_map_.get();
  110. }
  111. const std::u16string& BookmarkNode::GetTitledUrlNodeTitle() const {
  112. return GetTitle();
  113. }
  114. const GURL& BookmarkNode::GetTitledUrlNodeUrl() const {
  115. return url_;
  116. }
  117. std::vector<base::StringPiece16> BookmarkNode::GetTitledUrlNodeAncestorTitles()
  118. const {
  119. std::vector<base::StringPiece16> paths;
  120. for (const BookmarkNode* n = this; n->parent(); n = n->parent())
  121. paths.push_back(n->parent()->GetTitle());
  122. return paths;
  123. }
  124. BookmarkNode::BookmarkNode(int64_t id,
  125. const base::GUID& guid,
  126. const GURL& url,
  127. Type type,
  128. bool is_permanent_node)
  129. : id_(id),
  130. guid_(guid),
  131. url_(url),
  132. type_(type),
  133. date_added_(base::Time::Now()),
  134. is_permanent_node_(is_permanent_node) {
  135. DCHECK_NE(type == URL, url.is_empty());
  136. DCHECK(guid.is_valid());
  137. DCHECK_NE(guid.AsLowercaseString(), std::string(kBannedGuidDueToPastSyncBug));
  138. }
  139. void BookmarkNode::InvalidateFavicon() {
  140. icon_url_.reset();
  141. favicon_ = gfx::Image();
  142. favicon_state_ = INVALID_FAVICON;
  143. }
  144. // BookmarkPermanentNode -------------------------------------------------------
  145. // static
  146. std::unique_ptr<BookmarkPermanentNode>
  147. BookmarkPermanentNode::CreateManagedBookmarks(int64_t id) {
  148. // base::WrapUnique() used because the constructor is private.
  149. return base::WrapUnique(new BookmarkPermanentNode(
  150. id, FOLDER, base::GUID::ParseLowercase(kManagedNodeGuid),
  151. std::u16string(),
  152. /*visible_when_empty=*/false));
  153. }
  154. BookmarkPermanentNode::~BookmarkPermanentNode() = default;
  155. bool BookmarkPermanentNode::IsVisible() const {
  156. return visible_when_empty_ || !children().empty();
  157. }
  158. // static
  159. std::unique_ptr<BookmarkPermanentNode> BookmarkPermanentNode::CreateBookmarkBar(
  160. int64_t id,
  161. bool visible_when_empty) {
  162. // base::WrapUnique() used because the constructor is private.
  163. return base::WrapUnique(new BookmarkPermanentNode(
  164. id, BOOKMARK_BAR, base::GUID::ParseLowercase(kBookmarkBarNodeGuid),
  165. l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME),
  166. visible_when_empty));
  167. }
  168. // static
  169. std::unique_ptr<BookmarkPermanentNode>
  170. BookmarkPermanentNode::CreateOtherBookmarks(int64_t id,
  171. bool visible_when_empty) {
  172. // base::WrapUnique() used because the constructor is private.
  173. return base::WrapUnique(new BookmarkPermanentNode(
  174. id, OTHER_NODE, base::GUID::ParseLowercase(kOtherBookmarksNodeGuid),
  175. l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_OTHER_FOLDER_NAME),
  176. visible_when_empty));
  177. }
  178. // static
  179. std::unique_ptr<BookmarkPermanentNode>
  180. BookmarkPermanentNode::CreateMobileBookmarks(int64_t id,
  181. bool visible_when_empty) {
  182. // base::WrapUnique() used because the constructor is private.
  183. return base::WrapUnique(new BookmarkPermanentNode(
  184. id, MOBILE, base::GUID::ParseLowercase(kMobileBookmarksNodeGuid),
  185. l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_MOBILE_FOLDER_NAME),
  186. visible_when_empty));
  187. }
  188. BookmarkPermanentNode::BookmarkPermanentNode(int64_t id,
  189. Type type,
  190. const base::GUID& guid,
  191. const std::u16string& title,
  192. bool visible_when_empty)
  193. : BookmarkNode(id, guid, GURL(), type, /*is_permanent_node=*/true),
  194. visible_when_empty_(visible_when_empty) {
  195. DCHECK(type != URL);
  196. SetTitle(title);
  197. }
  198. } // namespace bookmarks