Vectorize website settings icons in omnibox
[chromium-blink-merge.git] / components / bookmarks / managed / managed_bookmarks_tracker.cc
blobbb7e42fd584c05a3f8e2a0a98f7c57f8fe6a9bf8
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.
5 #include "components/bookmarks/managed/managed_bookmarks_tracker.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/logging.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "components/bookmarks/browser/bookmark_model.h"
17 #include "components/bookmarks/browser/bookmark_node.h"
18 #include "components/bookmarks/common/bookmark_pref_names.h"
19 #include "grit/components_strings.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "url/gurl.h"
23 namespace bookmarks {
25 const char ManagedBookmarksTracker::kName[] = "name";
26 const char ManagedBookmarksTracker::kUrl[] = "url";
27 const char ManagedBookmarksTracker::kChildren[] = "children";
29 ManagedBookmarksTracker::ManagedBookmarksTracker(
30 BookmarkModel* model,
31 PrefService* prefs,
32 bool is_supervised,
33 const GetManagementDomainCallback& callback)
34 : model_(model),
35 is_supervised_(is_supervised),
36 managed_node_(NULL),
37 prefs_(prefs),
38 get_management_domain_callback_(callback) {
41 ManagedBookmarksTracker::~ManagedBookmarksTracker() {}
43 scoped_ptr<base::ListValue>
44 ManagedBookmarksTracker::GetInitialManagedBookmarks() {
45 const base::ListValue* list = prefs_->GetList(GetPrefName());
46 return make_scoped_ptr(list->DeepCopy());
49 // static
50 int64 ManagedBookmarksTracker::LoadInitial(BookmarkNode* folder,
51 const base::ListValue* list,
52 int64 next_node_id) {
53 for (size_t i = 0; i < list->GetSize(); ++i) {
54 // Extract the data for the next bookmark from the |list|.
55 base::string16 title;
56 GURL url;
57 const base::ListValue* children = NULL;
58 if (!LoadBookmark(list, i, &title, &url, &children))
59 continue;
61 BookmarkNode* child = new BookmarkNode(next_node_id++, url);
62 child->SetTitle(title);
63 folder->Add(child, folder->child_count());
64 if (children) {
65 child->set_type(BookmarkNode::FOLDER);
66 child->set_date_folder_modified(base::Time::Now());
67 next_node_id = LoadInitial(child, children, next_node_id);
68 } else {
69 child->set_type(BookmarkNode::URL);
70 child->set_date_added(base::Time::Now());
74 return next_node_id;
77 void ManagedBookmarksTracker::Init(BookmarkPermanentNode* managed_node) {
78 managed_node_ = managed_node;
79 registrar_.Init(prefs_);
80 registrar_.Add(GetPrefName(),
81 base::Bind(&ManagedBookmarksTracker::ReloadManagedBookmarks,
82 base::Unretained(this)));
83 // Reload now just in case something changed since the initial load started.
84 // Note that if we track managed bookmarks rather than supervised bookmarks,
85 // then we must not load them until cloud policy system has been fully
86 // initialized (which will make our preference a managed preference).
87 const bool are_managed_bookmarks_available =
88 is_supervised_ || prefs_->IsManagedPreference(GetPrefName());
89 if (are_managed_bookmarks_available)
90 ReloadManagedBookmarks();
93 // static
94 const char* ManagedBookmarksTracker::GetPrefName(bool is_supervised) {
95 return is_supervised ? prefs::kSupervisedBookmarks
96 : prefs::kManagedBookmarks;
99 const char* ManagedBookmarksTracker::GetPrefName() const {
100 return GetPrefName(is_supervised_);
103 base::string16 ManagedBookmarksTracker::GetBookmarksFolderTitle() const {
104 if (is_supervised_) {
105 return l10n_util::GetStringUTF16(
106 IDS_BOOKMARK_BAR_SUPERVISED_FOLDER_DEFAULT_NAME);
107 } else {
108 const std::string domain = get_management_domain_callback_.Run();
109 if (domain.empty()) {
110 return l10n_util::GetStringUTF16(
111 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME);
112 } else {
113 return l10n_util::GetStringFUTF16(
114 IDS_BOOKMARK_BAR_MANAGED_FOLDER_DOMAIN_NAME,
115 base::UTF8ToUTF16(domain));
120 void ManagedBookmarksTracker::ReloadManagedBookmarks() {
121 // In case the user just signed into or out of the account.
122 model_->SetTitle(managed_node_, GetBookmarksFolderTitle());
124 // Recursively update all the managed bookmarks and folders.
125 const base::ListValue* list = prefs_->GetList(GetPrefName());
126 UpdateBookmarks(managed_node_, list);
128 // The managed bookmarks folder isn't visible when that pref isn't present.
129 managed_node_->set_visible(!managed_node_->empty());
132 void ManagedBookmarksTracker::UpdateBookmarks(const BookmarkNode* folder,
133 const base::ListValue* list) {
134 int folder_index = 0;
135 for (size_t i = 0; i < list->GetSize(); ++i) {
136 // Extract the data for the next bookmark from the |list|.
137 base::string16 title;
138 GURL url;
139 const base::ListValue* children = NULL;
140 if (!LoadBookmark(list, i, &title, &url, &children)) {
141 // Skip this bookmark from |list| but don't advance |folder_index|.
142 continue;
145 // Look for a bookmark at |folder_index| or ahead that matches the current
146 // bookmark from the pref.
147 const BookmarkNode* existing = NULL;
148 for (int k = folder_index; k < folder->child_count(); ++k) {
149 const BookmarkNode* node = folder->GetChild(k);
150 if (node->GetTitle() == title &&
151 ((children && node->is_folder()) ||
152 (!children && node->url() == url))) {
153 existing = node;
154 break;
158 if (existing) {
159 // Reuse the existing node. The Move() is a nop if |existing| is already
160 // at |folder_index|.
161 model_->Move(existing, folder, folder_index);
162 if (children)
163 UpdateBookmarks(existing, children);
164 } else {
165 // Create a new node for this bookmark now.
166 if (children) {
167 const BookmarkNode* sub =
168 model_->AddFolder(folder, folder_index, title);
169 UpdateBookmarks(sub, children);
170 } else {
171 model_->AddURL(folder, folder_index, title, url);
175 // The |folder_index| index of |folder| has been updated, so advance it.
176 ++folder_index;
179 // Remove any extra children of |folder| that haven't been reused.
180 while (folder->child_count() != folder_index)
181 model_->Remove(folder->GetChild(folder_index));
184 // static
185 bool ManagedBookmarksTracker::LoadBookmark(const base::ListValue* list,
186 size_t index,
187 base::string16* title,
188 GURL* url,
189 const base::ListValue** children) {
190 std::string spec;
191 *url = GURL();
192 *children = NULL;
193 const base::DictionaryValue* dict = NULL;
194 if (!list->GetDictionary(index, &dict) ||
195 !dict->GetString(kName, title) ||
196 (!dict->GetString(kUrl, &spec) &&
197 !dict->GetList(kChildren, children))) {
198 // Should never happen after policy validation.
199 NOTREACHED();
200 return false;
202 if (!*children) {
203 *url = GURL(spec);
204 DCHECK(url->is_valid());
206 return true;
209 } // namespace policy