OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 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_user_service.h" |
| 6 |
| 7 #include "base/memory/ref_counted.h" |
| 8 #include "base/sequenced_task_runner.h" |
| 9 #include "chrome/browser/extensions/extension_service.h" |
| 10 #include "chrome/browser/extensions/extension_system.h" |
| 11 #include "chrome/browser/managed_mode/managed_mode_site_list.h" |
| 12 #include "chrome/browser/prefs/pref_service.h" |
| 13 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 14 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/common/chrome_notification_types.h" |
| 16 #include "chrome/common/extensions/extension_set.h" |
| 17 #include "chrome/common/pref_names.h" |
| 18 #include "content/public/browser/browser_thread.h" |
| 19 #include "grit/generated_resources.h" |
| 20 #include "ui/base/l10n/l10n_util.h" |
| 21 |
| 22 using content::BrowserThread; |
| 23 |
| 24 ManagedUserService::URLFilterContext::URLFilterContext() |
| 25 : ui_url_filter_(new ManagedModeURLFilter), |
| 26 io_url_filter_(new ManagedModeURLFilter) {} |
| 27 ManagedUserService::URLFilterContext::~URLFilterContext() {} |
| 28 |
| 29 ManagedModeURLFilter* |
| 30 ManagedUserService::URLFilterContext::ui_url_filter() const { |
| 31 return ui_url_filter_.get(); |
| 32 } |
| 33 |
| 34 ManagedModeURLFilter* |
| 35 ManagedUserService::URLFilterContext::io_url_filter() const { |
| 36 return io_url_filter_.get(); |
| 37 } |
| 38 |
| 39 void ManagedUserService::URLFilterContext::SetDefaultFilteringBehavior( |
| 40 ManagedModeURLFilter::FilteringBehavior behavior) { |
| 41 ui_url_filter_->SetDefaultFilteringBehavior(behavior); |
| 42 BrowserThread::PostTask( |
| 43 BrowserThread::IO, |
| 44 FROM_HERE, |
| 45 base::Bind(&ManagedModeURLFilter::SetDefaultFilteringBehavior, |
| 46 io_url_filter_.get(), |
| 47 behavior)); |
| 48 } |
| 49 |
| 50 void ManagedUserService::URLFilterContext::LoadWhitelists( |
| 51 ScopedVector<ManagedModeSiteList> site_lists) { |
| 52 // ManagedModeURLFilter::LoadWhitelists takes ownership of |site_lists|, |
| 53 // so we make an additional copy of it. |
| 54 /// TODO(bauerb): This is kinda ugly. |
| 55 ScopedVector<ManagedModeSiteList> site_lists_copy; |
| 56 for (ScopedVector<ManagedModeSiteList>::iterator it = site_lists.begin(); |
| 57 it != site_lists.end(); ++it) { |
| 58 site_lists_copy.push_back((*it)->Clone()); |
| 59 } |
| 60 ui_url_filter_->LoadWhitelists(site_lists.Pass()); |
| 61 BrowserThread::PostTask( |
| 62 BrowserThread::IO, |
| 63 FROM_HERE, |
| 64 base::Bind(&ManagedModeURLFilter::LoadWhitelists, |
| 65 io_url_filter_, |
| 66 base::Passed(&site_lists_copy))); |
| 67 } |
| 68 |
| 69 void ManagedUserService::URLFilterContext::SetManualLists( |
| 70 scoped_ptr<ListValue> whitelist, |
| 71 scoped_ptr<ListValue> blacklist) { |
| 72 ui_url_filter_->SetManualLists(whitelist.get(), blacklist.get()); |
| 73 BrowserThread::PostTask( |
| 74 BrowserThread::IO, |
| 75 FROM_HERE, |
| 76 base::Bind(&ManagedModeURLFilter::SetManualLists, |
| 77 io_url_filter_, |
| 78 base::Owned(whitelist.release()), |
| 79 base::Owned(blacklist.release()))); |
| 80 } |
| 81 |
| 82 void ManagedUserService::URLFilterContext::AddURLPatternToManualList( |
| 83 const bool is_whitelist, |
| 84 const std::string& url) { |
| 85 ui_url_filter_->AddURLPatternToManualList(is_whitelist, url); |
| 86 BrowserThread::PostTask( |
| 87 BrowserThread::IO, |
| 88 FROM_HERE, |
| 89 base::Bind(&ManagedModeURLFilter::AddURLPatternToManualList, |
| 90 io_url_filter_, |
| 91 is_whitelist, |
| 92 url)); |
| 93 } |
| 94 |
| 95 ManagedUserService::ManagedUserService(Profile* profile) |
| 96 : profile_(profile), |
| 97 is_elevated_(false) { |
| 98 Init(); |
| 99 } |
| 100 |
| 101 ManagedUserService::~ManagedUserService() { |
| 102 } |
| 103 |
| 104 bool ManagedUserService::ProfileIsManaged() const { |
| 105 return profile_->GetPrefs()->GetBoolean(prefs::kProfileIsManaged); |
| 106 } |
| 107 |
| 108 // static |
| 109 void ManagedUserService::RegisterUserPrefs(PrefServiceSyncable* prefs) { |
| 110 prefs->RegisterListPref(prefs::kManagedModeWhitelist, |
| 111 PrefServiceSyncable::UNSYNCABLE_PREF); |
| 112 prefs->RegisterListPref(prefs::kManagedModeBlacklist, |
| 113 PrefServiceSyncable::UNSYNCABLE_PREF); |
| 114 prefs->RegisterIntegerPref(prefs::kDefaultManagedModeFilteringBehavior, |
| 115 ManagedModeURLFilter::BLOCK, |
| 116 PrefServiceSyncable::UNSYNCABLE_PREF); |
| 117 } |
| 118 |
| 119 scoped_refptr<const ManagedModeURLFilter> |
| 120 ManagedUserService::GetURLFilterForIOThread() { |
| 121 return url_filter_context_.io_url_filter(); |
| 122 } |
| 123 |
| 124 ManagedModeURLFilter* ManagedUserService::GetURLFilterForUIThread() { |
| 125 return url_filter_context_.ui_url_filter(); |
| 126 } |
| 127 |
| 128 // Items not on any list must return -1 (CATEGORY_NOT_ON_LIST in history.js). |
| 129 // Items on a list, but with no category, must return 0 (CATEGORY_OTHER). |
| 130 #define CATEGORY_NOT_ON_LIST -1; |
| 131 #define CATEGORY_OTHER 0; |
| 132 |
| 133 int ManagedUserService::GetCategory(const GURL& url) { |
| 134 std::vector<ManagedModeSiteList::Site*> sites; |
| 135 GetURLFilterForUIThread()->GetSites(url, &sites); |
| 136 if (sites.empty()) |
| 137 return CATEGORY_NOT_ON_LIST; |
| 138 |
| 139 return (*sites.begin())->category_id; |
| 140 } |
| 141 |
| 142 // static |
| 143 void ManagedUserService::GetCategoryNames(CategoryList* list) { |
| 144 ManagedModeSiteList::GetCategoryNames(list); |
| 145 }; |
| 146 |
| 147 void ManagedUserService::AddToManualList(bool is_whitelist, |
| 148 const base::ListValue& list) { |
| 149 ListPrefUpdate pref_update(profile_->GetPrefs(), |
| 150 is_whitelist ? prefs::kManagedModeWhitelist : |
| 151 prefs::kManagedModeBlacklist); |
| 152 ListValue* pref_list = pref_update.Get(); |
| 153 |
| 154 for (size_t i = 0; i < list.GetSize(); ++i) { |
| 155 std::string url_pattern; |
| 156 list.GetString(i, &url_pattern); |
| 157 |
| 158 if (!IsInManualList(is_whitelist, url_pattern)) { |
| 159 pref_list->AppendString(url_pattern); |
| 160 AddURLPatternToManualList(is_whitelist, url_pattern); |
| 161 } |
| 162 } |
| 163 } |
| 164 |
| 165 void ManagedUserService::RemoveFromManualList(bool is_whitelist, |
| 166 const base::ListValue& list) { |
| 167 ListPrefUpdate pref_update(profile_->GetPrefs(), |
| 168 is_whitelist ? prefs::kManagedModeWhitelist : |
| 169 prefs::kManagedModeBlacklist); |
| 170 ListValue* pref_list = pref_update.Get(); |
| 171 |
| 172 for (size_t i = 0; i < list.GetSize(); ++i) { |
| 173 std::string pattern; |
| 174 size_t out_index; |
| 175 list.GetString(i, &pattern); |
| 176 StringValue value_to_remove(pattern); |
| 177 |
| 178 pref_list->Remove(value_to_remove, &out_index); |
| 179 } |
| 180 } |
| 181 |
| 182 bool ManagedUserService::IsInManualList(bool is_whitelist, |
| 183 const std::string& url_pattern) { |
| 184 StringValue pattern(url_pattern); |
| 185 const ListValue* list = profile_->GetPrefs()->GetList( |
| 186 is_whitelist ? prefs::kManagedModeWhitelist : |
| 187 prefs::kManagedModeBlacklist); |
| 188 return list->Find(pattern) != list->end(); |
| 189 } |
| 190 |
| 191 // static |
| 192 scoped_ptr<base::ListValue> ManagedUserService::GetBlacklist() { |
| 193 return make_scoped_ptr( |
| 194 profile_->GetPrefs()->GetList(prefs::kManagedModeBlacklist)->DeepCopy()); |
| 195 } |
| 196 |
| 197 std::string ManagedUserService::GetDebugPolicyProviderName() const { |
| 198 // Save the string space in official builds. |
| 199 #ifdef NDEBUG |
| 200 NOTREACHED(); |
| 201 return std::string(); |
| 202 #else |
| 203 return "Managed User Service"; |
| 204 #endif |
| 205 } |
| 206 |
| 207 bool ManagedUserService::UserMayLoad(const extensions::Extension* extension, |
| 208 string16* error) const { |
| 209 string16 tmp_error; |
| 210 if (ExtensionManagementPolicyImpl(&tmp_error)) |
| 211 return true; |
| 212 |
| 213 // If the extension is already loaded, we allow it, otherwise we'd unload |
| 214 // all existing extensions. |
| 215 ExtensionService* extension_service = |
| 216 extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 217 |
| 218 // |extension_service| can be NULL in a unit test. |
| 219 if (extension_service && |
| 220 extension_service->GetInstalledExtension(extension->id())) |
| 221 return true; |
| 222 |
| 223 if (error) |
| 224 *error = tmp_error; |
| 225 return false; |
| 226 } |
| 227 |
| 228 bool ManagedUserService::UserMayModifySettings( |
| 229 const extensions::Extension* extension, |
| 230 string16* error) const { |
| 231 return ExtensionManagementPolicyImpl(error); |
| 232 } |
| 233 |
| 234 void ManagedUserService::Observe(int type, |
| 235 const content::NotificationSource& source, |
| 236 const content::NotificationDetails& details) { |
| 237 switch (type) { |
| 238 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
| 239 const extensions::Extension* extension = |
| 240 content::Details<extensions::Extension>(details).ptr(); |
| 241 if (!extension->GetContentPackSiteList().empty()) |
| 242 UpdateSiteLists(); |
| 243 |
| 244 break; |
| 245 } |
| 246 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
| 247 const extensions::UnloadedExtensionInfo* extension_info = |
| 248 content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); |
| 249 if (!extension_info->extension->GetContentPackSiteList().empty()) |
| 250 UpdateSiteLists(); |
| 251 |
| 252 break; |
| 253 } |
| 254 default: |
| 255 NOTREACHED(); |
| 256 } |
| 257 } |
| 258 |
| 259 bool ManagedUserService::ExtensionManagementPolicyImpl(string16* error) const { |
| 260 if (!ProfileIsManaged()) |
| 261 return true; |
| 262 |
| 263 if (is_elevated_) |
| 264 return true; |
| 265 |
| 266 if (error) |
| 267 *error = l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_MODE); |
| 268 return false; |
| 269 } |
| 270 |
| 271 ScopedVector<ManagedModeSiteList> ManagedUserService::GetActiveSiteLists() { |
| 272 ScopedVector<ManagedModeSiteList> site_lists; |
| 273 ExtensionService* extension_service = |
| 274 extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 275 // Can be NULL in unit tests. |
| 276 if (!extension_service) |
| 277 return site_lists.Pass(); |
| 278 |
| 279 const ExtensionSet* extensions = extension_service->extensions(); |
| 280 for (ExtensionSet::const_iterator it = extensions->begin(); |
| 281 it != extensions->end(); ++it) { |
| 282 const extensions::Extension* extension = *it; |
| 283 if (!extension_service->IsExtensionEnabled(extension->id())) |
| 284 continue; |
| 285 |
| 286 ExtensionResource site_list = extension->GetContentPackSiteList(); |
| 287 if (!site_list.empty()) |
| 288 site_lists.push_back(new ManagedModeSiteList(extension->id(), site_list)); |
| 289 } |
| 290 |
| 291 return site_lists.Pass(); |
| 292 } |
| 293 |
| 294 void ManagedUserService::OnDefaultFilteringBehaviorChanged() { |
| 295 DCHECK(ProfileIsManaged()); |
| 296 |
| 297 int behavior_value = profile_->GetPrefs()->GetInteger( |
| 298 prefs::kDefaultManagedModeFilteringBehavior); |
| 299 ManagedModeURLFilter::FilteringBehavior behavior = |
| 300 ManagedModeURLFilter::BehaviorFromInt(behavior_value); |
| 301 url_filter_context_.SetDefaultFilteringBehavior(behavior); |
| 302 } |
| 303 |
| 304 void ManagedUserService::UpdateSiteLists() { |
| 305 url_filter_context_.LoadWhitelists(GetActiveSiteLists()); |
| 306 } |
| 307 |
| 308 void ManagedUserService::UpdateManualLists() { |
| 309 url_filter_context_.SetManualLists(GetWhitelist(), GetBlacklist()); |
| 310 } |
| 311 |
| 312 void ManagedUserService::SetElevatedForTesting(bool is_elevated) { |
| 313 is_elevated_ = is_elevated; |
| 314 } |
| 315 |
| 316 void ManagedUserService::Init() { |
| 317 if (!ProfileIsManaged()) |
| 318 return; |
| 319 |
| 320 extensions::ExtensionSystem* extension_system = |
| 321 extensions::ExtensionSystem::Get(profile_); |
| 322 extensions::ManagementPolicy* management_policy = |
| 323 extension_system->management_policy(); |
| 324 if (management_policy) |
| 325 extension_system->management_policy()->RegisterProvider(this); |
| 326 |
| 327 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
| 328 content::Source<Profile>(profile_)); |
| 329 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 330 content::Source<Profile>(profile_)); |
| 331 pref_change_registrar_.Init(profile_->GetPrefs()); |
| 332 pref_change_registrar_.Add( |
| 333 prefs::kDefaultManagedModeFilteringBehavior, |
| 334 base::Bind( |
| 335 &ManagedUserService::OnDefaultFilteringBehaviorChanged, |
| 336 base::Unretained(this))); |
| 337 |
| 338 // Initialize the filter. |
| 339 OnDefaultFilteringBehaviorChanged(); |
| 340 UpdateSiteLists(); |
| 341 UpdateManualLists(); |
| 342 } |
| 343 |
| 344 scoped_ptr<base::ListValue> ManagedUserService::GetWhitelist() { |
| 345 return make_scoped_ptr( |
| 346 profile_->GetPrefs()->GetList(prefs::kManagedModeWhitelist)->DeepCopy()); |
| 347 } |
| 348 |
| 349 void ManagedUserService::AddURLPatternToManualList( |
| 350 bool is_whitelist, |
| 351 const std::string& url_pattern) { |
| 352 url_filter_context_.AddURLPatternToManualList(true, url_pattern); |
| 353 } |
OLD | NEW |