Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / managed_mode / managed_mode_site_list.cc
blobe254381b14081568eba97526c12e51b1fd63a5fc
1 // Copyright (c) 2012 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 "chrome/browser/managed_mode/managed_mode_site_list.h"
7 #include "base/json/json_file_value_serializer.h"
8 #include "base/logging.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "extensions/common/extension.h"
13 using base::DictionaryValue;
14 using base::ListValue;
15 using base::Value;
17 const int kSitelistFormatVersion = 1;
19 const char kCategoriesKey[] = "categories";
20 const char kHostnameHashesKey[] = "hostname_hashes";
21 const char kNameKey[] = "name";
22 const char kSitesKey[] = "sites";
23 const char kSitelistFormatVersionKey[] = "version";
24 const char kThumbnailKey[] = "thumbnail";
25 const char kThumbnailUrlKey[] = "thumbnail_url";
26 const char kUrlKey[] = "url";
27 const char kWhitelistKey[] = "whitelist";
29 namespace {
31 struct CategoryInfo {
32 const char* identifier;
33 const char* name;
36 // These are placeholders for now.
37 CategoryInfo g_categories[] = {
38 {"com.google.chrome.animals", "Animals and Plants"},
39 {"com.google.chrome.arts", "Arts"},
40 {"com.google.chrome.business", "Business"},
41 {"com.google.chrome.computers", "Computers"},
42 {"com.google.chrome.education", "Education"},
43 {"com.google.chrome.entertainment", "Entertainment"},
44 {"com.google.chrome.games", "Games"},
45 {"com.google.chrome.health", "Health"},
46 {"com.google.chrome.home", "Home"},
47 {"com.google.chrome.international", "International"},
48 {"com.google.chrome.news", "News"},
49 {"com.google.chrome.people", "People and Society"},
50 {"com.google.chrome.places", "Places"},
51 {"com.google.chrome.pre-school", "Pre-School"},
52 {"com.google.chrome.reference", "Reference"},
53 {"com.google.chrome.science", "Science"},
54 {"com.google.chrome.shopping", "Shopping"},
55 {"com.google.chrome.sports", "Sports and Hobbies"},
56 {"com.google.chrome.teens", "Teens"}
59 // Category 0 is "not listed"; actual category IDs start at 1.
60 int GetCategoryId(const std::string& category) {
61 for (size_t i = 0; i < arraysize(g_categories); ++i) {
62 if (g_categories[i].identifier == category)
63 return i + 1;
65 return 0;
68 // Takes a DictionaryValue entry from the JSON file and fills the whitelist
69 // (via URL patterns or hostname hashes) and the URL in the corresponding Site
70 // struct.
71 void AddWhitelistEntries(const base::DictionaryValue* site_dict,
72 ManagedModeSiteList::Site* site) {
73 std::vector<std::string>* patterns = &site->patterns;
75 bool found = false;
76 const base::ListValue* whitelist = NULL;
77 if (site_dict->GetList(kWhitelistKey, &whitelist)) {
78 found = true;
79 for (base::ListValue::const_iterator whitelist_it = whitelist->begin();
80 whitelist_it != whitelist->end(); ++whitelist_it) {
81 std::string pattern;
82 if (!(*whitelist_it)->GetAsString(&pattern)) {
83 LOG(ERROR) << "Invalid whitelist entry";
84 continue;
87 patterns->push_back(pattern);
91 std::vector<std::string>* hashes = &site->hostname_hashes;
92 const base::ListValue* hash_list = NULL;
93 if (site_dict->GetList(kHostnameHashesKey, &hash_list)) {
94 found = true;
95 for (base::ListValue::const_iterator hash_list_it = hash_list->begin();
96 hash_list_it != hash_list->end(); ++hash_list_it) {
97 std::string hash;
98 if (!(*hash_list_it)->GetAsString(&hash)) {
99 LOG(ERROR) << "Invalid whitelist entry";
100 continue;
103 hashes->push_back(hash);
107 if (found)
108 return;
110 // Fall back to using a whitelist based on the URL.
111 std::string url_str;
112 if (!site_dict->GetString(kUrlKey, &url_str)) {
113 LOG(ERROR) << "Whitelist is invalid";
114 return;
117 GURL url(url_str);
118 if (!url.is_valid()) {
119 LOG(ERROR) << "URL " << url_str << " is invalid";
120 return;
123 patterns->push_back(url.host());
126 } // namespace
128 ManagedModeSiteList::Site::Site(const base::string16& name,
129 int category_id)
130 : name(name),
131 category_id(category_id) {}
133 ManagedModeSiteList::Site::~Site() {}
135 ManagedModeSiteList::ManagedModeSiteList(
136 const std::string& extension_id,
137 const base::FilePath& path)
138 : extension_id_(extension_id),
139 path_(path) {
142 ManagedModeSiteList::~ManagedModeSiteList() {
145 ManagedModeSiteList* ManagedModeSiteList::Clone() {
146 return new ManagedModeSiteList(extension_id_, path_);
149 // static
150 void ManagedModeSiteList::GetCategoryNames(
151 std::vector<base::string16>* categories) {
152 // TODO(bauerb): Collect custom categories from extensions.
153 for (size_t i = 0; i < arraysize(g_categories); ++i) {
154 categories->push_back(base::ASCIIToUTF16(g_categories[i].name));
158 void ManagedModeSiteList::GetSites(std::vector<Site>* sites) {
159 if (!LazyLoad())
160 return;
162 for (base::ListValue::iterator entry_it = sites_->begin();
163 entry_it != sites_->end(); ++entry_it) {
164 base::DictionaryValue* entry = NULL;
165 if (!(*entry_it)->GetAsDictionary(&entry)) {
166 LOG(ERROR) << "Entry is invalid";
167 continue;
170 base::string16 name;
171 entry->GetString(kNameKey, &name);
173 // TODO(bauerb): We need to distinguish between "no category assigned" and
174 // "not on any site list".
175 int category_id = 0;
176 const base::ListValue* categories = NULL;
177 if (entry->GetList(kCategoriesKey, &categories)) {
178 for (base::ListValue::const_iterator it = categories->begin();
179 it != categories->end(); ++it) {
180 std::string category;
181 if (!(*it)->GetAsString(&category)) {
182 LOG(ERROR) << "Invalid category";
183 continue;
185 category_id = GetCategoryId(category);
186 break;
189 sites->push_back(Site(name, category_id));
190 AddWhitelistEntries(entry, &sites->back());
194 bool ManagedModeSiteList::LazyLoad() {
195 if (sites_.get())
196 return true;
198 JSONFileValueSerializer serializer(path_);
199 std::string error;
200 scoped_ptr<base::Value> value(serializer.Deserialize(NULL, &error));
201 if (!value.get()) {
202 LOG(ERROR) << "Couldn't load site list " << path_.value() << ": "
203 << error;
204 return false;
207 base::DictionaryValue* dict = NULL;
208 if (!value->GetAsDictionary(&dict)) {
209 LOG(ERROR) << "Site list " << path_.value() << " is invalid";
210 return false;
213 int version = 0;
214 if (!dict->GetInteger(kSitelistFormatVersionKey, &version)) {
215 LOG(ERROR) << "Site list " << path_.value() << " has invalid version";
216 return false;
219 if (version > kSitelistFormatVersion) {
220 LOG(ERROR) << "Site list " << path_.value() << " has a too new format";
221 return false;
224 base::ListValue* sites = NULL;
225 if (dict->GetList(kSitesKey, &sites))
226 sites_.reset(sites->DeepCopy());
228 base::DictionaryValue* categories = NULL;
229 if (dict->GetDictionary(kCategoriesKey, &categories))
230 categories_.reset(categories->DeepCopy());
232 return true;
235 void ManagedModeSiteList::CopyThumbnailUrl(const base::DictionaryValue* source,
236 base::DictionaryValue* dest) {
237 if (!source->HasKey(kThumbnailKey))
238 return;
240 std::string thumbnail;
241 if (!source->GetString(kThumbnailKey, &thumbnail)) {
242 LOG(ERROR) << "Invalid thumbnail";
243 return;
246 GURL base_url =
247 extensions::Extension::GetBaseURLFromExtensionId(extension_id_);
248 GURL thumbnail_url = base_url.Resolve(thumbnail);
249 if (!thumbnail_url.is_valid()) {
250 LOG(ERROR) << "Invalid thumbnail";
251 return;
254 dest->SetString(kThumbnailUrlKey, thumbnail_url.spec());