OLD | NEW |
---|---|
(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 const char kKeyLink[] = "SupervisedBookmarkLink"; | |
Pam (message me for reviews)
2015/01/14 14:03:37
A little more description of where these keys appl
Marc Treib
2015/01/14 16:40:50
Done.
| |
15 const char kKeyFolder[] = "SupervisedBookmarkFolder"; | |
16 | |
17 const char kId[] = "id"; | |
18 const char kName[] = "name"; | |
19 const char kUrl[] = "url"; | |
20 const char kChildren[] = "children"; | |
21 | |
22 bool ExtractId(const std::string& key, int* id) { | |
23 // |key| can be either "<ID>-<Value>" or just "<ID>". | |
Pam (message me for reviews)
2015/01/14 14:03:37
Under what circumstances does each of these |key|
Marc Treib
2015/01/14 16:40:50
Updated the comment. And yes, that should be ":",
| |
24 std::string id_str = key.substr(0, key.find_first_of(':')); | |
25 if (!base::StringToInt(id_str, id)) { | |
26 LOG(WARNING) << "Failed to parse id from " << key; | |
27 return false; | |
28 } | |
29 LOG_IF(WARNING, *id < 0) << "IDs should be >= 0, but got " | |
30 << *id << " from " << key; | |
31 return true; | |
32 } | |
33 | |
34 bool ExtractValue(const std::string& key, std::string* value) { | |
35 // |key| must be "<ID>-<Value>". | |
Pam (message me for reviews)
2015/01/14 14:03:37
- --> :
Marc Treib
2015/01/14 16:40:50
Done.
| |
36 size_t pos = key.find_first_of(':'); | |
37 if (pos == std::string::npos) { | |
38 LOG(WARNING) << "Failed to parse value from " << key; | |
39 return false; | |
40 } | |
41 *value = key.substr(pos + 1); | |
42 return true; | |
43 } | |
44 | |
45 bool ExtractIdAndValue(const std::string& key, int* id, std::string* value) { | |
46 return ExtractId(key, id) && ExtractValue(key, value); | |
47 } | |
48 | |
49 base::ListValue* FindNode(base::ListValue* root, int id) { | |
Pam (message me for reviews)
2015/01/14 14:03:37
FindFolder would be a clearer function name. Also,
Marc Treib
2015/01/14 16:40:50
Done.
| |
50 if (id == 0) // We're looking for the root folder. Assume this is it. | |
51 return root; | |
52 | |
53 for (size_t i = 0; i < root->GetSize(); ++i) { | |
54 base::DictionaryValue* item = nullptr; | |
55 root->GetDictionary(i, &item); | |
56 DCHECK_NE(item, (base::DictionaryValue*)nullptr); | |
57 | |
58 base::ListValue* children; | |
59 if (!item->GetList(kChildren, &children)) | |
60 continue; // Skip bookmarks. Only interested in folders. | |
61 | |
62 // Is this it? | |
63 int node_id; | |
64 if (item->GetInteger(kId, &node_id) && node_id == id) | |
65 return children; | |
66 | |
67 // Recurse. | |
68 base::ListValue* result = FindNode(children, id); | |
69 if (result) | |
70 return result; | |
71 } | |
72 return nullptr; | |
73 } | |
74 | |
75 } // namespace | |
76 | |
77 SupervisedUserBookmarksHandler::Folder::Folder( | |
78 int id, const std::string& name, int parent_id) | |
79 : id(id), name(name), parent_id(parent_id) { | |
80 } | |
81 | |
82 SupervisedUserBookmarksHandler::Link::Link( | |
83 const std::string& url, const std::string& name, int parent_id) | |
84 : url(url), name(name), parent_id(parent_id) { | |
85 } | |
86 | |
87 SupervisedUserBookmarksHandler::SupervisedUserBookmarksHandler() { | |
88 } | |
89 | |
90 SupervisedUserBookmarksHandler::~SupervisedUserBookmarksHandler() { | |
91 } | |
92 | |
93 scoped_ptr<base::ListValue> SupervisedUserBookmarksHandler::BuildBookmarksTree( | |
94 const base::DictionaryValue& settings) { | |
95 SupervisedUserBookmarksHandler handler; | |
96 handler.ParseSettings(settings); | |
97 return handler.BuildTree(); | |
98 } | |
99 | |
100 void SupervisedUserBookmarksHandler::ParseSettings( | |
101 const base::DictionaryValue& settings) { | |
102 const base::DictionaryValue* folders; | |
103 if (settings.GetDictionary(kKeyFolder, &folders)) | |
104 ParseFolders(*folders); | |
105 | |
106 const base::DictionaryValue* links; | |
107 if (settings.GetDictionary(kKeyLink, &links)) | |
108 ParseLinks(*links); | |
109 } | |
110 | |
111 void SupervisedUserBookmarksHandler::ParseFolders( | |
112 const base::DictionaryValue& folders) { | |
113 for (base::DictionaryValue::Iterator it(folders); !it.IsAtEnd(); | |
114 it.Advance()) { | |
115 int id; | |
116 if (!ExtractId(it.key(), &id)) | |
117 continue; | |
118 std::string value; | |
119 it.value().GetAsString(&value); | |
120 std::string name; | |
121 int parent_id; | |
122 if (!ExtractIdAndValue(value, &parent_id, &name)) | |
123 continue; | |
124 folders_.push_back(Folder(id, name, parent_id)); | |
125 } | |
126 } | |
127 | |
128 void SupervisedUserBookmarksHandler::ParseLinks( | |
129 const base::DictionaryValue& links) { | |
130 for (base::DictionaryValue::Iterator it(links); !it.IsAtEnd(); it.Advance()) { | |
131 std::string url; | |
132 if (!ExtractValue(it.key(), &url)) | |
133 continue; | |
134 std::string value; | |
135 it.value().GetAsString(&value); | |
136 std::string name; | |
137 int parent_id; | |
138 if (!ExtractIdAndValue(value, &parent_id, &name)) | |
139 continue; | |
140 links_.push_back(Link(url, name, parent_id)); | |
Pam (message me for reviews)
2015/01/14 14:03:37
I'm almost tempted to make a union for id|url, and
Marc Treib
2015/01/14 16:40:50
Hrm. I agree that the mostly-duplicated code isn't
Pam (message me for reviews)
2015/01/15 11:37:04
Could also be a struct or class with separate url
| |
141 } | |
142 } | |
143 | |
144 scoped_ptr<base::ListValue> SupervisedUserBookmarksHandler::BuildTree() { | |
145 root_.reset(new base::ListValue); | |
146 AddFoldersToTree(); | |
147 AddLinksToTree(); | |
148 return root_.Pass(); | |
149 } | |
150 | |
151 void SupervisedUserBookmarksHandler::AddFoldersToTree() { | |
152 std::vector<Folder> folders = folders_; | |
153 std::vector<Folder> folders_failed; | |
154 while (!folders.empty() && folders.size() != folders_failed.size()) { | |
Pam (message me for reviews)
2015/01/14 14:03:37
This snippet is a bit hard to understand. A commen
Marc Treib
2015/01/14 16:40:50
Done.
| |
155 folders_failed.clear(); | |
156 for (const auto& folder : folders) { | |
157 scoped_ptr<base::DictionaryValue> node(new base::DictionaryValue); | |
158 node->SetIntegerWithoutPathExpansion(kId, folder.id); | |
159 node->SetStringWithoutPathExpansion(kName, folder.name); | |
160 node->SetWithoutPathExpansion(kChildren, new base::ListValue); | |
161 if (!AddNodeToTree(folder.parent_id, node.Pass())) | |
162 folders_failed.push_back(folder); | |
163 } | |
164 folders.swap(folders_failed); | |
165 } | |
166 } | |
167 | |
168 void SupervisedUserBookmarksHandler::AddLinksToTree() { | |
169 for (const auto& link : links_) { | |
170 scoped_ptr<base::DictionaryValue> node(new base::DictionaryValue); | |
171 GURL url = url_fixer::FixupURL(link.url, std::string()); | |
172 if (!url.is_valid()) { | |
173 DLOG(WARNING) << "Got invalid URL: " << link.url; | |
174 continue; | |
175 } | |
176 node->SetStringWithoutPathExpansion(kUrl, url.spec()); | |
177 node->SetStringWithoutPathExpansion(kName, link.name); | |
178 AddNodeToTree(link.parent_id, node.Pass()); | |
Pam (message me for reviews)
2015/01/14 14:03:37
Also consider logging a warning if the bookmark ca
Marc Treib
2015/01/14 16:40:50
Done.
| |
179 } | |
180 } | |
181 | |
182 bool SupervisedUserBookmarksHandler::AddNodeToTree( | |
183 int parent_id, | |
184 scoped_ptr<base::DictionaryValue> node) { | |
185 base::ListValue* parent = FindNode(root_.get(), parent_id); | |
186 if (!parent) | |
187 return false; | |
188 parent->Append(node.release()); | |
189 return true; | |
190 } | |
OLD | NEW |