| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "chrome/browser/managed_mode/managed_mode_site_list.h" | |
| 6 | |
| 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" | |
| 12 | |
| 13 using base::DictionaryValue; | |
| 14 using base::ListValue; | |
| 15 using base::Value; | |
| 16 | |
| 17 const int kSitelistFormatVersion = 1; | |
| 18 | |
| 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"; | |
| 28 | |
| 29 namespace { | |
| 30 | |
| 31 struct CategoryInfo { | |
| 32 const char* identifier; | |
| 33 const char* name; | |
| 34 }; | |
| 35 | |
| 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"} | |
| 57 }; | |
| 58 | |
| 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; | |
| 64 } | |
| 65 return 0; | |
| 66 } | |
| 67 | |
| 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; | |
| 74 | |
| 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; | |
| 85 } | |
| 86 | |
| 87 patterns->push_back(pattern); | |
| 88 } | |
| 89 } | |
| 90 | |
| 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; | |
| 101 } | |
| 102 | |
| 103 hashes->push_back(hash); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 if (found) | |
| 108 return; | |
| 109 | |
| 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; | |
| 115 } | |
| 116 | |
| 117 GURL url(url_str); | |
| 118 if (!url.is_valid()) { | |
| 119 LOG(ERROR) << "URL " << url_str << " is invalid"; | |
| 120 return; | |
| 121 } | |
| 122 | |
| 123 patterns->push_back(url.host()); | |
| 124 } | |
| 125 | |
| 126 } // namespace | |
| 127 | |
| 128 ManagedModeSiteList::Site::Site(const base::string16& name, | |
| 129 int category_id) | |
| 130 : name(name), | |
| 131 category_id(category_id) {} | |
| 132 | |
| 133 ManagedModeSiteList::Site::~Site() {} | |
| 134 | |
| 135 ManagedModeSiteList::ManagedModeSiteList( | |
| 136 const std::string& extension_id, | |
| 137 const base::FilePath& path) | |
| 138 : extension_id_(extension_id), | |
| 139 path_(path) { | |
| 140 } | |
| 141 | |
| 142 ManagedModeSiteList::~ManagedModeSiteList() { | |
| 143 } | |
| 144 | |
| 145 ManagedModeSiteList* ManagedModeSiteList::Clone() { | |
| 146 return new ManagedModeSiteList(extension_id_, path_); | |
| 147 } | |
| 148 | |
| 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)); | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 void ManagedModeSiteList::GetSites(std::vector<Site>* sites) { | |
| 159 if (!LazyLoad()) | |
| 160 return; | |
| 161 | |
| 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; | |
| 168 } | |
| 169 | |
| 170 base::string16 name; | |
| 171 entry->GetString(kNameKey, &name); | |
| 172 | |
| 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; | |
| 184 } | |
| 185 category_id = GetCategoryId(category); | |
| 186 break; | |
| 187 } | |
| 188 } | |
| 189 sites->push_back(Site(name, category_id)); | |
| 190 AddWhitelistEntries(entry, &sites->back()); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 bool ManagedModeSiteList::LazyLoad() { | |
| 195 if (sites_.get()) | |
| 196 return true; | |
| 197 | |
| 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; | |
| 205 } | |
| 206 | |
| 207 base::DictionaryValue* dict = NULL; | |
| 208 if (!value->GetAsDictionary(&dict)) { | |
| 209 LOG(ERROR) << "Site list " << path_.value() << " is invalid"; | |
| 210 return false; | |
| 211 } | |
| 212 | |
| 213 int version = 0; | |
| 214 if (!dict->GetInteger(kSitelistFormatVersionKey, &version)) { | |
| 215 LOG(ERROR) << "Site list " << path_.value() << " has invalid version"; | |
| 216 return false; | |
| 217 } | |
| 218 | |
| 219 if (version > kSitelistFormatVersion) { | |
| 220 LOG(ERROR) << "Site list " << path_.value() << " has a too new format"; | |
| 221 return false; | |
| 222 } | |
| 223 | |
| 224 base::ListValue* sites = NULL; | |
| 225 if (dict->GetList(kSitesKey, &sites)) | |
| 226 sites_.reset(sites->DeepCopy()); | |
| 227 | |
| 228 base::DictionaryValue* categories = NULL; | |
| 229 if (dict->GetDictionary(kCategoriesKey, &categories)) | |
| 230 categories_.reset(categories->DeepCopy()); | |
| 231 | |
| 232 return true; | |
| 233 } | |
| 234 | |
| 235 void ManagedModeSiteList::CopyThumbnailUrl(const base::DictionaryValue* source, | |
| 236 base::DictionaryValue* dest) { | |
| 237 if (!source->HasKey(kThumbnailKey)) | |
| 238 return; | |
| 239 | |
| 240 std::string thumbnail; | |
| 241 if (!source->GetString(kThumbnailKey, &thumbnail)) { | |
| 242 LOG(ERROR) << "Invalid thumbnail"; | |
| 243 return; | |
| 244 } | |
| 245 | |
| 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; | |
| 252 } | |
| 253 | |
| 254 dest->SetString(kThumbnailUrlKey, thumbnail_url.spec()); | |
| 255 } | |
| OLD | NEW |