Chromium Code Reviews| 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 |