Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Side by Side Diff: chrome/browser/supervised_user/supervised_user_bookmarks_handler.cc

Issue 769153007: Managed bookmarks for supervised users (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: string change Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
5 #include "chrome/browser/supervised_user/supervised_user_bookmarks_handler.h"
6
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/values.h"
10 #include "components/url_fixer/url_fixer.h"
11
12 namespace {
13
14 // Keys of relevant managed user settings.
15 const char kKeyLink[] = "SupervisedBookmarkLink";
16 const char kKeyFolder[] = "SupervisedBookmarkFolder";
17
18 // Keys for elements of the bookmarks json tree.
19 const char kId[] = "id";
20 const char kName[] = "name";
21 const char kUrl[] = "url";
22 const char kChildren[] = "children";
23
24 bool ExtractId(const std::string& key, int* id) {
25 // |key| can be either "<ID>:<Value>" (for links and for "parentID:name"
26 // pairs) or just "<ID>" (for folders).
27 std::string id_str = key.substr(0, key.find_first_of(':'));
28 if (!base::StringToInt(id_str, id)) {
29 LOG(WARNING) << "Failed to parse id from " << key;
30 return false;
31 }
32 LOG_IF(WARNING, *id < 0) << "IDs should be >= 0, but got "
33 << *id << " from " << key;
34 return true;
35 }
36
37 bool ExtractValue(const std::string& key, std::string* value) {
38 // |key| must be "<ID>:<Value>".
39 size_t pos = key.find_first_of(':');
40 if (pos == std::string::npos) {
41 LOG(WARNING) << "Failed to parse value from " << key;
42 return false;
43 }
44 *value = key.substr(pos + 1);
45 return true;
46 }
47
48 bool ExtractIdAndValue(const std::string& key, int* id, std::string* value) {
49 return ExtractId(key, id) && ExtractValue(key, value);
50 }
51
52 // Recursively searches the tree from |root| for a folder with the given |id|.
53 // Returns the list of children of that folder if found, otherwise returns null.
54 base::ListValue* FindFolder(base::ListValue* root, int id) {
55 if (id == 0) // We're looking for the root folder. Assume this is it.
56 return root;
57
58 for (size_t i = 0; i < root->GetSize(); ++i) {
59 base::DictionaryValue* item = nullptr;
60 root->GetDictionary(i, &item);
61 DCHECK_NE(item, (base::DictionaryValue*)nullptr);
62
63 base::ListValue* children;
64 if (!item->GetList(kChildren, &children))
65 continue; // Skip bookmarks. Only interested in folders.
66
67 // Is this it?
68 int node_id;
69 if (item->GetInteger(kId, &node_id) && node_id == id)
70 return children;
71
72 // Recurse.
73 base::ListValue* result = FindFolder(children, id);
74 if (result)
75 return result;
76 }
77 return nullptr;
78 }
79
80 } // namespace
81
82 SupervisedUserBookmarksHandler::Folder::Folder(
83 int id, const std::string& name, int parent_id)
84 : id(id), name(name), parent_id(parent_id) {
85 }
86
87 SupervisedUserBookmarksHandler::Link::Link(
88 const std::string& url, const std::string& name, int parent_id)
89 : url(url), name(name), parent_id(parent_id) {
90 }
91
92 SupervisedUserBookmarksHandler::SupervisedUserBookmarksHandler() {
93 }
94
95 SupervisedUserBookmarksHandler::~SupervisedUserBookmarksHandler() {
96 }
97
98 scoped_ptr<base::ListValue> SupervisedUserBookmarksHandler::BuildBookmarksTree(
99 const base::DictionaryValue& settings) {
100 SupervisedUserBookmarksHandler handler;
101 handler.ParseSettings(settings);
102 return handler.BuildTree();
103 }
104
105 void SupervisedUserBookmarksHandler::ParseSettings(
106 const base::DictionaryValue& settings) {
107 const base::DictionaryValue* folders;
108 if (settings.GetDictionary(kKeyFolder, &folders))
109 ParseFolders(*folders);
110
111 const base::DictionaryValue* links;
112 if (settings.GetDictionary(kKeyLink, &links))
113 ParseLinks(*links);
114 }
115
116 void SupervisedUserBookmarksHandler::ParseFolders(
117 const base::DictionaryValue& folders) {
118 for (base::DictionaryValue::Iterator it(folders); !it.IsAtEnd();
119 it.Advance()) {
120 int id;
121 if (!ExtractId(it.key(), &id))
122 continue;
123 std::string value;
124 it.value().GetAsString(&value);
125 std::string name;
126 int parent_id;
127 if (!ExtractIdAndValue(value, &parent_id, &name))
128 continue;
129 folders_.push_back(Folder(id, name, parent_id));
130 }
131 }
132
133 void SupervisedUserBookmarksHandler::ParseLinks(
134 const base::DictionaryValue& links) {
135 for (base::DictionaryValue::Iterator it(links); !it.IsAtEnd(); it.Advance()) {
136 std::string url;
137 if (!ExtractValue(it.key(), &url))
138 continue;
139 std::string value;
140 it.value().GetAsString(&value);
141 std::string name;
142 int parent_id;
143 if (!ExtractIdAndValue(value, &parent_id, &name))
144 continue;
145 links_.push_back(Link(url, name, parent_id));
146 }
147 }
148
149 scoped_ptr<base::ListValue> SupervisedUserBookmarksHandler::BuildTree() {
150 root_.reset(new base::ListValue);
151 AddFoldersToTree();
152 AddLinksToTree();
153 return root_.Pass();
154 }
155
156 void SupervisedUserBookmarksHandler::AddFoldersToTree() {
157 // Go over all folders and try inserting them into the correct position in the
158 // tree. This requires the respective parent folder to be there already. Since
159 // the parent might appear later in |folders_|, we might need multiple rounds
160 // until all folders can be added successfully.
161 // To avoid an infinite loop in the case of a non-existing parent, we take
162 // care to stop when no folders could be added in a round.
163 std::vector<Folder> folders = folders_;
164 std::vector<Folder> folders_failed;
165 while (!folders.empty() && folders.size() != folders_failed.size()) {
166 folders_failed.clear();
167 for (const auto& folder : folders) {
168 scoped_ptr<base::DictionaryValue> node(new base::DictionaryValue);
169 node->SetIntegerWithoutPathExpansion(kId, folder.id);
170 node->SetStringWithoutPathExpansion(kName, folder.name);
171 node->SetWithoutPathExpansion(kChildren, new base::ListValue);
172 if (!AddNodeToTree(folder.parent_id, node.Pass()))
173 folders_failed.push_back(folder);
174 }
175 folders.swap(folders_failed);
176 }
177 if (!folders_failed.empty()) {
178 LOG(WARNING) << "SupervisedUserBookmarksHandler::AddFoldersToTree"
179 << " failed adding the following folders (id,name,parent):";
180 for (const Folder& folder : folders_failed) {
181 LOG(WARNING) << folder.id << ", " << folder.name << ", "
182 << folder.parent_id;
183 }
184 }
185 }
186
187 void SupervisedUserBookmarksHandler::AddLinksToTree() {
188 for (const auto& link : links_) {
189 scoped_ptr<base::DictionaryValue> node(new base::DictionaryValue);
190 GURL url = url_fixer::FixupURL(link.url, std::string());
191 if (!url.is_valid()) {
192 LOG(WARNING) << "Got invalid URL: " << link.url;
193 continue;
194 }
195 node->SetStringWithoutPathExpansion(kUrl, url.spec());
196 node->SetStringWithoutPathExpansion(kName, link.name);
197 if (!AddNodeToTree(link.parent_id, node.Pass())) {
198 LOG(WARNING) << "SupervisedUserBookmarksHandler::AddLinksToTree"
199 << " failed to add link (url,name,parent): "
200 << link.url << ", " << link.name << ", " << link.parent_id;
201 }
202 }
203 }
204
205 bool SupervisedUserBookmarksHandler::AddNodeToTree(
206 int parent_id,
207 scoped_ptr<base::DictionaryValue> node) {
208 base::ListValue* parent = FindFolder(root_.get(), parent_id);
209 if (!parent)
210 return false;
211 parent->Append(node.release());
212 return true;
213 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698