blob: b2625451afd82c35db1c022c6174ef060835cc4b [file] [log] [blame]
[email protected]cce15bb2014-06-17 13:43:511// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]0850e842013-01-19 03:44:312// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]cce15bb2014-06-17 13:43:515#include "chrome/browser/supervised_user/supervised_user_service.h"
[email protected]0850e842013-01-19 03:44:316
dchenge73d8520c2015-12-27 01:19:097#include <utility>
8
mamire9609642016-06-28 22:17:549#include "base/feature_list.h"
treibdaece84f2014-09-05 12:58:1510#include "base/files/file_path.h"
treib2fd187392015-04-16 17:19:3811#include "base/files/file_util.h"
Marc Treib9d91df552018-09-27 14:55:5512#include "base/memory/scoped_refptr.h"
bratell0a7406f2017-03-28 07:46:3713#include "base/metrics/user_metrics.h"
treibd3f8b7a2015-04-10 11:41:3314#include "base/path_service.h"
treib40d3ad92015-10-20 18:15:4215#include "base/strings/stringprintf.h"
[email protected]112158af2013-06-07 23:46:1816#include "base/strings/utf_string_conversions.h"
Gabriel Charette44db1422018-08-06 11:19:3317#include "base/task/post_task.h"
treibf832a992015-03-24 18:09:2418#include "base/version.h"
avi664c07b2015-12-26 02:18:3119#include "build/build_config.h"
[email protected]5ddfade2014-02-03 10:24:5320#include "chrome/browser/browser_process.h"
bauerb4da36132014-12-26 19:53:1321#include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
[email protected]0850e842013-01-19 03:44:3122#include "chrome/browser/profiles/profile.h"
[email protected]aab946912013-11-06 22:18:5123#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
treibe2082a0e2015-04-08 10:15:3024#include "chrome/browser/supervised_user/experimental/supervised_user_filtering_switches.h"
bauerb5f8cda92015-10-07 15:36:4425#include "chrome/browser/supervised_user/permission_request_creator.h"
[email protected]cce15bb2014-06-17 13:43:5126#include "chrome/browser/supervised_user/supervised_user_constants.h"
mamire9609642016-06-28 22:17:5427#include "chrome/browser/supervised_user/supervised_user_features.h"
mamire9609642016-06-28 22:17:5428#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
treibab0a39e2014-09-24 14:48:2829#include "chrome/browser/supervised_user/supervised_user_service_observer.h"
[email protected]cce15bb2014-06-17 13:43:5130#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
31#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
[email protected]cce15bb2014-06-17 13:43:5132#include "chrome/browser/supervised_user/supervised_user_site_list.h"
bauerb4da36132014-12-26 19:53:1333#include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
[email protected]a19df3e2013-05-21 00:03:0334#include "chrome/browser/sync/profile_sync_service_factory.h"
[email protected]509ad1a92013-03-19 21:41:0635#include "chrome/browser/ui/browser.h"
[email protected]dfddd022013-07-10 17:29:4836#include "chrome/browser/ui/browser_list.h"
treibd3f8b7a2015-04-10 11:41:3337#include "chrome/common/chrome_paths.h"
[email protected]0850e842013-01-19 03:44:3138#include "chrome/common/pref_names.h"
[email protected]af39f002014-08-22 10:18:1839#include "chrome/grit/generated_resources.h"
maxbogue26f40222016-09-16 20:22:1840#include "components/browser_sync/profile_sync_service.h"
Michael Giuffrida0fe58bf2018-07-26 20:40:2741#include "components/policy/core/browser/url_util.h"
[email protected]f0c8c4992014-05-15 17:37:2642#include "components/pref_registry/pref_registry_syncable.h"
brettwb1fc1b82016-02-02 00:19:0843#include "components/prefs/pref_service.h"
[email protected]7274ef02014-03-24 22:43:4044#include "components/signin/core/browser/profile_oauth2_token_service.h"
Mark Pilgrima8b7f432018-04-19 23:23:0045#include "content/public/browser/browser_context.h"
Mark Pilgrima8b7f432018-04-19 23:23:0046#include "content/public/browser/storage_partition.h"
Scott Violetc8240b02018-03-08 22:03:5947#include "extensions/buildflags/buildflags.h"
rhalavati5f1caa2b2017-02-25 08:22:1648#include "net/traffic_annotation/network_traffic_annotation.h"
Mark Pilgrimb67362ed2018-05-15 15:59:4749#include "services/network/public/cpp/shared_url_loader_factory.h"
[email protected]0850e842013-01-19 03:44:3150#include "ui/base/l10n/l10n_util.h"
51
jam1c5a91492016-02-24 20:47:5352#if !defined(OS_ANDROID)
brettw9b0866f2016-12-11 02:34:0653#include "chrome/browser/themes/theme_service.h"
54#include "chrome/browser/themes/theme_service_factory.h"
thestig1b76f1a2015-09-30 22:52:3855#endif
56
[email protected]3aacc9c2013-08-08 11:19:3157#if defined(OS_CHROMEOS)
[email protected]4d390782014-08-15 09:22:5858#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
[email protected]83d82d42014-05-16 02:04:4259#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
[email protected]4d390782014-08-15 09:22:5860#include "components/user_manager/user_manager.h"
[email protected]3aacc9c2013-08-08 11:19:3161#endif
62
brettw00899e62016-11-12 02:10:1763#if BUILDFLAG(ENABLE_EXTENSIONS)
treib9e30e302015-04-15 08:12:1664#include "chrome/browser/extensions/extension_service.h"
mamir192d7882016-06-22 17:10:1665#include "chrome/browser/extensions/extension_util.h"
66#include "extensions/browser/extension_prefs.h"
mamire9609642016-06-28 22:17:5467#include "extensions/browser/extension_registry.h"
[email protected]c14a6802014-07-11 21:51:1268#include "extensions/browser/extension_system.h"
[email protected]c14a6802014-07-11 21:51:1269#endif
70
[email protected]2056c3b2014-04-07 18:08:5071using base::UserMetricsAction;
[email protected]0850e842013-01-19 03:44:3172
brettw00899e62016-11-12 02:10:1773#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:5474using extensions::Extension;
75using extensions::ExtensionPrefs;
76using extensions::ExtensionRegistry;
77using extensions::ExtensionSystem;
78#endif
79
treib22c3a042015-01-15 21:30:1380namespace {
81
treibd3f8b7a2015-04-10 11:41:3382// The URL from which to download a host blacklist if no local one exists yet.
83const char kBlacklistURL[] =
84 "https://www.gstatic.com/chrome/supervised_user/blacklist-20141001-1k.bin";
85// The filename under which we'll store the blacklist (in the user data dir).
86const char kBlacklistFilename[] = "su-blacklist.bin";
87
treib22c3a042015-01-15 21:30:1388const char* const kCustodianInfoPrefs[] = {
89 prefs::kSupervisedUserCustodianName,
90 prefs::kSupervisedUserCustodianEmail,
91 prefs::kSupervisedUserCustodianProfileImageURL,
92 prefs::kSupervisedUserCustodianProfileURL,
93 prefs::kSupervisedUserSecondCustodianName,
94 prefs::kSupervisedUserSecondCustodianEmail,
95 prefs::kSupervisedUserSecondCustodianProfileImageURL,
96 prefs::kSupervisedUserSecondCustodianProfileURL,
97};
98
Carlos IL6b784a62018-03-20 00:26:4999void CreateURLAccessRequest(const GURL& url,
100 PermissionRequestCreator* creator,
101 SupervisedUserService::SuccessCallback callback) {
102 creator->CreateURLAccessRequest(url, std::move(callback));
treib8ecc1eb52015-03-04 18:29:06103}
104
mamire9609642016-06-28 22:17:54105void CreateExtensionInstallRequest(
106 const std::string& id,
107 PermissionRequestCreator* creator,
Carlos IL6b784a62018-03-20 00:26:49108 SupervisedUserService::SuccessCallback callback) {
109 creator->CreateExtensionInstallRequest(id, std::move(callback));
mamire9609642016-06-28 22:17:54110}
111
treib8ecc1eb52015-03-04 18:29:06112void CreateExtensionUpdateRequest(
treibf832a992015-03-24 18:09:24113 const std::string& id,
treib8ecc1eb52015-03-04 18:29:06114 PermissionRequestCreator* creator,
Carlos IL6b784a62018-03-20 00:26:49115 SupervisedUserService::SuccessCallback callback) {
116 creator->CreateExtensionUpdateRequest(id, std::move(callback));
treib8ecc1eb52015-03-04 18:29:06117}
118
mamire9609642016-06-28 22:17:54119// Default callback for AddExtensionInstallRequest.
120void ExtensionInstallRequestSent(const std::string& id, bool success) {
121 VLOG_IF(1, !success) << "Failed sending install request for " << id;
122}
123
treib40d3ad92015-10-20 18:15:42124// Default callback for AddExtensionUpdateRequest.
125void ExtensionUpdateRequestSent(const std::string& id, bool success) {
126 VLOG_IF(1, !success) << "Failed sending update request for " << id;
127}
128
treibd3f8b7a2015-04-10 11:41:33129base::FilePath GetBlacklistPath() {
130 base::FilePath blacklist_dir;
Avi Drissman9098f9002018-05-04 00:11:52131 base::PathService::Get(chrome::DIR_USER_DATA, &blacklist_dir);
treibd3f8b7a2015-04-10 11:41:33132 return blacklist_dir.AppendASCII(kBlacklistFilename);
133}
134
treib22c3a042015-01-15 21:30:13135} // namespace
136
bauerb5f8cda92015-10-07 15:36:44137SupervisedUserService::~SupervisedUserService() {
138 DCHECK(!did_init_ || did_shutdown_);
mmenkedb2637ff2017-03-30 23:59:42139 url_filter_.RemoveObserver(this);
bauerb5f8cda92015-10-07 15:36:44140}
141
142// static
143void SupervisedUserService::RegisterProfilePrefs(
144 user_prefs::PrefRegistrySyncable* registry) {
mamire9609642016-06-28 22:17:54145 registry->RegisterDictionaryPref(prefs::kSupervisedUserApprovedExtensions);
bauerb5f8cda92015-10-07 15:36:44146 registry->RegisterDictionaryPref(prefs::kSupervisedUserManualHosts);
147 registry->RegisterDictionaryPref(prefs::kSupervisedUserManualURLs);
148 registry->RegisterIntegerPref(prefs::kDefaultSupervisedUserFilteringBehavior,
149 SupervisedUserURLFilter::ALLOW);
bauerb5f8cda92015-10-07 15:36:44150 registry->RegisterBooleanPref(prefs::kSupervisedUserSafeSites, true);
151 for (const char* pref : kCustodianInfoPrefs) {
152 registry->RegisterStringPref(pref, std::string());
153 }
154}
155
156void SupervisedUserService::Init() {
157 DCHECK(!did_init_);
158 did_init_ = true;
159 DCHECK(GetSettingsService()->IsReady());
160
161 pref_change_registrar_.Init(profile_->GetPrefs());
162 pref_change_registrar_.Add(
163 prefs::kSupervisedUserId,
164 base::Bind(&SupervisedUserService::OnSupervisedUserIdChanged,
165 base::Unretained(this)));
166 pref_change_registrar_.Add(
bauerbb519f8252016-05-13 09:16:39167 prefs::kForceSessionSync,
168 base::Bind(&SupervisedUserService::OnForceSessionSyncChanged,
bauerb5f8cda92015-10-07 15:36:44169 base::Unretained(this)));
170
maxbogue0a379452016-09-22 21:35:05171 browser_sync::ProfileSyncService* sync_service =
bauerb5f8cda92015-10-07 15:36:44172 ProfileSyncServiceFactory::GetForProfile(profile_);
173 // Can be null in tests.
174 if (sync_service)
175 sync_service->AddPreferenceProvider(this);
176
177 std::string client_id = component_updater::SupervisedUserWhitelistInstaller::
178 ClientIdForProfilePath(profile_->GetPath());
179 whitelist_service_.reset(new SupervisedUserWhitelistService(
180 profile_->GetPrefs(),
181 g_browser_process->supervised_user_whitelist_installer(), client_id));
182 whitelist_service_->AddSiteListsChangedCallback(
183 base::Bind(&SupervisedUserService::OnSiteListsChanged,
184 weak_ptr_factory_.GetWeakPtr()));
185
186 SetActive(ProfileIsSupervised());
187}
188
189void SupervisedUserService::SetDelegate(Delegate* delegate) {
190 if (delegate) {
191 // Changing delegates isn't allowed.
192 DCHECK(!delegate_);
193 } else {
194 // If the delegate is removed, deactivate first to give the old delegate a
195 // chance to clean up.
196 SetActive(false);
197 }
198 delegate_ = delegate;
199}
200
mmenkedb2637ff2017-03-30 23:59:42201SupervisedUserURLFilter* SupervisedUserService::GetURLFilter() {
202 return &url_filter_;
bauerb5f8cda92015-10-07 15:36:44203}
204
205SupervisedUserWhitelistService* SupervisedUserService::GetWhitelistService() {
206 return whitelist_service_.get();
207}
208
209bool SupervisedUserService::AccessRequestsEnabled() {
210 return FindEnabledPermissionRequestCreator(0) < permissions_creators_.size();
211}
212
Carlos IL6b784a62018-03-20 00:26:49213void SupervisedUserService::AddURLAccessRequest(const GURL& url,
214 SuccessCallback callback) {
Michael Giuffrida0fe58bf2018-07-26 20:40:27215 GURL effective_url = policy::url_util::GetEmbeddedURL(url);
treib17f2e382016-10-14 11:42:53216 if (!effective_url.is_valid())
217 effective_url = url;
bauerb5f8cda92015-10-07 15:36:44218 AddPermissionRequestInternal(
Carlos IL6b784a62018-03-20 00:26:49219 base::BindRepeating(CreateURLAccessRequest,
Michael Giuffrida0fe58bf2018-07-26 20:40:27220 policy::url_util::Normalize(effective_url)),
Carlos IL6b784a62018-03-20 00:26:49221 std::move(callback), 0);
bauerb5f8cda92015-10-07 15:36:44222}
223
atanasovaac676032016-04-05 16:31:05224void SupervisedUserService::ReportURL(const GURL& url,
Carlos IL6b784a62018-03-20 00:26:49225 SuccessCallback callback) {
atanasovaac676032016-04-05 16:31:05226 if (url_reporter_)
Carlos IL6b784a62018-03-20 00:26:49227 url_reporter_->ReportUrl(url, std::move(callback));
atanasovaac676032016-04-05 16:31:05228 else
Carlos IL6b784a62018-03-20 00:26:49229 std::move(callback).Run(false);
atanasovaac676032016-04-05 16:31:05230}
231
mamire9609642016-06-28 22:17:54232void SupervisedUserService::AddExtensionInstallRequest(
233 const std::string& extension_id,
234 const base::Version& version,
Carlos IL6b784a62018-03-20 00:26:49235 SuccessCallback callback) {
mamire9609642016-06-28 22:17:54236 std::string id = GetExtensionRequestId(extension_id, version);
Carlos IL6b784a62018-03-20 00:26:49237 AddPermissionRequestInternal(
238 base::BindRepeating(CreateExtensionInstallRequest, id),
239 std::move(callback), 0);
mamire9609642016-06-28 22:17:54240}
241
242void SupervisedUserService::AddExtensionInstallRequest(
243 const std::string& extension_id,
244 const base::Version& version) {
245 std::string id = GetExtensionRequestId(extension_id, version);
Carlos IL6b784a62018-03-20 00:26:49246 AddExtensionInstallRequest(extension_id, version,
247 base::BindOnce(ExtensionInstallRequestSent, id));
mamire9609642016-06-28 22:17:54248}
249
bauerb5f8cda92015-10-07 15:36:44250void SupervisedUserService::AddExtensionUpdateRequest(
251 const std::string& extension_id,
252 const base::Version& version,
Carlos IL6b784a62018-03-20 00:26:49253 SuccessCallback callback) {
mamire9609642016-06-28 22:17:54254 std::string id = GetExtensionRequestId(extension_id, version);
bauerb5f8cda92015-10-07 15:36:44255 AddPermissionRequestInternal(
Carlos IL6b784a62018-03-20 00:26:49256 base::BindRepeating(CreateExtensionUpdateRequest, id),
257 std::move(callback), 0);
treib40d3ad92015-10-20 18:15:42258}
259
260void SupervisedUserService::AddExtensionUpdateRequest(
261 const std::string& extension_id,
262 const base::Version& version) {
mamire9609642016-06-28 22:17:54263 std::string id = GetExtensionRequestId(extension_id, version);
treib40d3ad92015-10-20 18:15:42264 AddExtensionUpdateRequest(extension_id, version,
Carlos IL6b784a62018-03-20 00:26:49265 base::BindOnce(ExtensionUpdateRequestSent, id));
treib40d3ad92015-10-20 18:15:42266}
267
268// static
mamire9609642016-06-28 22:17:54269std::string SupervisedUserService::GetExtensionRequestId(
treib40d3ad92015-10-20 18:15:42270 const std::string& extension_id,
271 const base::Version& version) {
272 return base::StringPrintf("%s:%s", extension_id.c_str(),
273 version.GetString().c_str());
bauerb5f8cda92015-10-07 15:36:44274}
275
276std::string SupervisedUserService::GetCustodianEmailAddress() const {
treib2170ea02015-10-13 14:55:12277 std::string email = profile_->GetPrefs()->GetString(
bauerb5f8cda92015-10-07 15:36:44278 prefs::kSupervisedUserCustodianEmail);
279#if defined(OS_CHROMEOS)
treib2170ea02015-10-13 14:55:12280 // |GetActiveUser()| can return null in unit tests.
281 if (email.empty() && !!user_manager::UserManager::Get()->GetActiveUser()) {
282 email = chromeos::ChromeUserManager::Get()
alemate1e3ddde2016-11-04 02:17:06283 ->GetSupervisedUserManager()
284 ->GetManagerDisplayEmail(user_manager::UserManager::Get()
285 ->GetActiveUser()
286 ->GetAccountId()
287 .GetUserEmail());
bauerb5f8cda92015-10-07 15:36:44288 }
289#endif
treib2170ea02015-10-13 14:55:12290 return email;
bauerb5f8cda92015-10-07 15:36:44291}
292
293std::string SupervisedUserService::GetCustodianName() const {
294 std::string name = profile_->GetPrefs()->GetString(
295 prefs::kSupervisedUserCustodianName);
296#if defined(OS_CHROMEOS)
treib2170ea02015-10-13 14:55:12297 // |GetActiveUser()| can return null in unit tests.
298 if (name.empty() && !!user_manager::UserManager::Get()->GetActiveUser()) {
alemate1e3ddde2016-11-04 02:17:06299 name = base::UTF16ToUTF8(
300 chromeos::ChromeUserManager::Get()
301 ->GetSupervisedUserManager()
302 ->GetManagerDisplayName(user_manager::UserManager::Get()
303 ->GetActiveUser()
304 ->GetAccountId()
305 .GetUserEmail()));
bauerb5f8cda92015-10-07 15:36:44306 }
307#endif
308 return name.empty() ? GetCustodianEmailAddress() : name;
309}
310
311std::string SupervisedUserService::GetSecondCustodianEmailAddress() const {
312 return profile_->GetPrefs()->GetString(
313 prefs::kSupervisedUserSecondCustodianEmail);
314}
315
316std::string SupervisedUserService::GetSecondCustodianName() const {
317 std::string name = profile_->GetPrefs()->GetString(
318 prefs::kSupervisedUserSecondCustodianName);
319 return name.empty() ? GetSecondCustodianEmailAddress() : name;
320}
321
treib2170ea02015-10-13 14:55:12322base::string16 SupervisedUserService::GetExtensionsLockedMessage() const {
323 return l10n_util::GetStringFUTF16(IDS_EXTENSIONS_LOCKED_SUPERVISED_USER,
324 base::UTF8ToUTF16(GetCustodianName()));
325}
326
jam1c5a91492016-02-24 20:47:53327#if !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:44328void SupervisedUserService::InitSync(const std::string& refresh_token) {
bauerb5f8cda92015-10-07 15:36:44329 ProfileOAuth2TokenService* token_service =
330 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
331 token_service->UpdateCredentials(supervised_users::kSupervisedUserPseudoEmail,
332 refresh_token);
bauerb5f8cda92015-10-07 15:36:44333}
jam1c5a91492016-02-24 20:47:53334#endif // !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:44335
bauerb5f8cda92015-10-07 15:36:44336void SupervisedUserService::AddObserver(
337 SupervisedUserServiceObserver* observer) {
338 observer_list_.AddObserver(observer);
339}
340
341void SupervisedUserService::RemoveObserver(
342 SupervisedUserServiceObserver* observer) {
343 observer_list_.RemoveObserver(observer);
344}
345
346void SupervisedUserService::AddPermissionRequestCreator(
dchengf624e472016-04-12 08:33:17347 std::unique_ptr<PermissionRequestCreator> creator) {
leon.han4ea301f2017-03-28 03:36:31348 permissions_creators_.push_back(std::move(creator));
bauerb5f8cda92015-10-07 15:36:44349}
350
atanasovaac676032016-04-05 16:31:05351void SupervisedUserService::SetSafeSearchURLReporter(
dchengf624e472016-04-12 08:33:17352 std::unique_ptr<SafeSearchURLReporter> reporter) {
atanasovaac676032016-04-05 16:31:05353 url_reporter_ = std::move(reporter);
354}
355
bauerbb519f8252016-05-13 09:16:39356bool SupervisedUserService::IncludesSyncSessionsType() const {
357 return includes_sync_sessions_type_;
358}
359
[email protected]cce15bb2014-06-17 13:43:51360SupervisedUserService::SupervisedUserService(Profile* profile)
fhorschig1f351f02014-09-30 12:30:22361 : includes_sync_sessions_type_(true),
362 profile_(profile),
[email protected]f085fdd52014-06-11 18:09:20363 active_(false),
364 delegate_(NULL),
[email protected]dfddd022013-07-10 17:29:48365 is_profile_active_(false),
[email protected]3a276ff2014-08-12 14:22:09366 did_init_(false),
[email protected]8052b242013-11-15 16:40:55367 did_shutdown_(false),
treib9cc1b112016-01-08 10:08:01368 blacklist_state_(BlacklistLoadState::NOT_LOADED),
brettw00899e62016-11-12 02:10:17369#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54370 registry_observer_(this),
371#endif
[email protected]8052b242013-11-15 16:40:55372 weak_ptr_factory_(this) {
mmenkedb2637ff2017-03-30 23:59:42373 url_filter_.AddObserver(this);
brettw00899e62016-11-12 02:10:17374#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54375 registry_observer_.Add(extensions::ExtensionRegistry::Get(profile));
376#endif
[email protected]a243d644c2013-06-20 18:37:55377}
[email protected]0850e842013-01-19 03:44:31378
[email protected]cce15bb2014-06-17 13:43:51379void SupervisedUserService::SetActive(bool active) {
[email protected]f085fdd52014-06-11 18:09:20380 if (active_ == active)
[email protected]0850e842013-01-19 03:44:31381 return;
[email protected]f085fdd52014-06-11 18:09:20382 active_ = active;
383
384 if (!delegate_ || !delegate_->SetActive(active_)) {
385 if (active_) {
jam1c5a91492016-02-24 20:47:53386#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20387 ProfileOAuth2TokenService* token_service =
388 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
[email protected]cce15bb2014-06-17 13:43:51389 token_service->LoadCredentials(
390 supervised_users::kSupervisedUserPseudoEmail);
bauerb7f3b8542015-06-29 19:56:19391#else
392 NOTREACHED();
393#endif
[email protected]f085fdd52014-06-11 18:09:20394 }
[email protected]e861bba2013-06-17 15:20:54395 }
[email protected]0850e842013-01-19 03:44:31396
[email protected]f085fdd52014-06-11 18:09:20397 // Now activate/deactivate anything not handled by the delegate yet.
[email protected]e1480482013-09-11 11:49:58398
brettw9b0866f2016-12-11 02:34:06399#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20400 // Re-set the default theme to turn the SU theme on/off.
401 ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile_);
treib9e30e302015-04-15 08:12:16402 if (theme_service->UsingDefaultTheme() || theme_service->UsingSystemTheme())
403 theme_service->UseDefaultTheme();
[email protected]f085fdd52014-06-11 18:09:20404#endif
[email protected]a19df3e2013-05-21 00:03:03405
maxbogue0a379452016-09-22 21:35:05406 browser_sync::ProfileSyncService* sync_service =
bauerbf03588b92014-10-27 13:40:15407 ProfileSyncServiceFactory::GetForProfile(profile_);
408 sync_service->SetEncryptEverythingAllowed(!active_);
409
bauerbd3a36cc42014-10-01 13:05:49410 GetSettingsService()->SetActive(active_);
[email protected]a243d644c2013-06-20 18:37:55411
brettw00899e62016-11-12 02:10:17412#if BUILDFLAG(ENABLE_EXTENSIONS)
[email protected]c14a6802014-07-11 21:51:12413 SetExtensionsActive();
414#endif
[email protected]0850e842013-01-19 03:44:31415
[email protected]f085fdd52014-06-11 18:09:20416 if (active_) {
[email protected]f085fdd52014-06-11 18:09:20417 pref_change_registrar_.Add(
[email protected]d20d0432014-06-12 17:14:05418 prefs::kDefaultSupervisedUserFilteringBehavior,
Carlos IL6b784a62018-03-20 00:26:49419 base::BindRepeating(
420 &SupervisedUserService::OnDefaultFilteringBehaviorChanged,
[email protected]f085fdd52014-06-11 18:09:20421 base::Unretained(this)));
brettw00899e62016-11-12 02:10:17422#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54423 pref_change_registrar_.Add(
424 prefs::kSupervisedUserApprovedExtensions,
Carlos IL6b784a62018-03-20 00:26:49425 base::BindRepeating(&SupervisedUserService::UpdateApprovedExtensions,
426 base::Unretained(this)));
mamire9609642016-06-28 22:17:54427#endif
Carlos IL6b784a62018-03-20 00:26:49428 pref_change_registrar_.Add(
429 prefs::kSupervisedUserSafeSites,
430 base::BindRepeating(&SupervisedUserService::OnSafeSitesSettingChanged,
431 base::Unretained(this)));
432 pref_change_registrar_.Add(
433 prefs::kSupervisedUserManualHosts,
434 base::BindRepeating(&SupervisedUserService::UpdateManualHosts,
435 base::Unretained(this)));
436 pref_change_registrar_.Add(
437 prefs::kSupervisedUserManualURLs,
438 base::BindRepeating(&SupervisedUserService::UpdateManualURLs,
439 base::Unretained(this)));
treib22c3a042015-01-15 21:30:13440 for (const char* pref : kCustodianInfoPrefs) {
Carlos IL6b784a62018-03-20 00:26:49441 pref_change_registrar_.Add(
442 pref,
443 base::BindRepeating(&SupervisedUserService::OnCustodianInfoChanged,
444 base::Unretained(this)));
treib22c3a042015-01-15 21:30:13445 }
[email protected]f085fdd52014-06-11 18:09:20446
447 // Initialize the filter.
448 OnDefaultFilteringBehaviorChanged();
treib9cc1b112016-01-08 10:08:01449 OnSafeSitesSettingChanged();
bauerb4da36132014-12-26 19:53:13450 whitelist_service_->Init();
[email protected]f085fdd52014-06-11 18:09:20451 UpdateManualHosts();
452 UpdateManualURLs();
[email protected]0850e842013-01-19 03:44:31453
brettw00899e62016-11-12 02:10:17454#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54455 UpdateApprovedExtensions();
456#endif
457
jam1c5a91492016-02-24 20:47:53458#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20459 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
460 // http://crbug.com/313377
461 BrowserList::AddObserver(this);
[email protected]975677d2013-11-14 16:15:34462#endif
[email protected]f085fdd52014-06-11 18:09:20463 } else {
bauerbd3a36cc42014-10-01 13:05:49464 permissions_creators_.clear();
atanasovaac676032016-04-05 16:31:05465 url_reporter_.reset();
[email protected]dfddd022013-07-10 17:29:48466
[email protected]d20d0432014-06-12 17:14:05467 pref_change_registrar_.Remove(
468 prefs::kDefaultSupervisedUserFilteringBehavior);
brettw00899e62016-11-12 02:10:17469#if BUILDFLAG(ENABLE_EXTENSIONS)
mamire9609642016-06-28 22:17:54470 pref_change_registrar_.Remove(prefs::kSupervisedUserApprovedExtensions);
471#endif
[email protected]d20d0432014-06-12 17:14:05472 pref_change_registrar_.Remove(prefs::kSupervisedUserManualHosts);
473 pref_change_registrar_.Remove(prefs::kSupervisedUserManualURLs);
treib22c3a042015-01-15 21:30:13474 for (const char* pref : kCustodianInfoPrefs) {
475 pref_change_registrar_.Remove(pref);
476 }
477
mmenkedb2637ff2017-03-30 23:59:42478 url_filter_.Clear();
ericwilligers8b92b052016-10-19 22:21:58479 for (SupervisedUserServiceObserver& observer : observer_list_)
480 observer.OnURLFilterChanged();
[email protected]f085fdd52014-06-11 18:09:20481
jam1c5a91492016-02-24 20:47:53482#if !defined(OS_ANDROID)
[email protected]f085fdd52014-06-11 18:09:20483 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
484 // http://crbug.com/313377
485 BrowserList::RemoveObserver(this);
486#endif
487 }
[email protected]0850e842013-01-19 03:44:31488}
489
bauerb5f8cda92015-10-07 15:36:44490bool SupervisedUserService::ProfileIsSupervised() const {
491 return profile_->IsSupervised();
492}
493
494void SupervisedUserService::OnCustodianInfoChanged() {
ericwilligers8b92b052016-10-19 22:21:58495 for (SupervisedUserServiceObserver& observer : observer_list_)
496 observer.OnCustodianInfoChanged();
bauerb5f8cda92015-10-07 15:36:44497}
498
499SupervisedUserSettingsService* SupervisedUserService::GetSettingsService() {
500 return SupervisedUserSettingsServiceFactory::GetForProfile(profile_);
501}
502
503size_t SupervisedUserService::FindEnabledPermissionRequestCreator(
504 size_t start) {
505 for (size_t i = start; i < permissions_creators_.size(); ++i) {
506 if (permissions_creators_[i]->IsEnabled())
507 return i;
508 }
509 return permissions_creators_.size();
510}
511
512void SupervisedUserService::AddPermissionRequestInternal(
513 const CreatePermissionRequestCallback& create_request,
Carlos IL6b784a62018-03-20 00:26:49514 SuccessCallback callback,
bauerb5f8cda92015-10-07 15:36:44515 size_t index) {
516 // Find a permission request creator that is enabled.
517 size_t next_index = FindEnabledPermissionRequestCreator(index);
518 if (next_index >= permissions_creators_.size()) {
Carlos IL6b784a62018-03-20 00:26:49519 std::move(callback).Run(false);
bauerb5f8cda92015-10-07 15:36:44520 return;
521 }
522
523 create_request.Run(
leon.han4ea301f2017-03-28 03:36:31524 permissions_creators_[next_index].get(),
Carlos IL6b784a62018-03-20 00:26:49525 base::BindOnce(&SupervisedUserService::OnPermissionRequestIssued,
526 weak_ptr_factory_.GetWeakPtr(), create_request,
527 std::move(callback), next_index));
bauerb5f8cda92015-10-07 15:36:44528}
529
530void SupervisedUserService::OnPermissionRequestIssued(
531 const CreatePermissionRequestCallback& create_request,
Carlos IL6b784a62018-03-20 00:26:49532 SuccessCallback callback,
bauerb5f8cda92015-10-07 15:36:44533 size_t index,
534 bool success) {
535 if (success) {
Carlos IL6b784a62018-03-20 00:26:49536 std::move(callback).Run(true);
bauerb5f8cda92015-10-07 15:36:44537 return;
538 }
539
Carlos IL6b784a62018-03-20 00:26:49540 AddPermissionRequestInternal(create_request, std::move(callback), index + 1);
bauerb5f8cda92015-10-07 15:36:44541}
542
543void SupervisedUserService::OnSupervisedUserIdChanged() {
544 SetActive(ProfileIsSupervised());
545}
546
547void SupervisedUserService::OnDefaultFilteringBehaviorChanged() {
548 int behavior_value = profile_->GetPrefs()->GetInteger(
549 prefs::kDefaultSupervisedUserFilteringBehavior);
550 SupervisedUserURLFilter::FilteringBehavior behavior =
551 SupervisedUserURLFilter::BehaviorFromInt(behavior_value);
mmenkedb2637ff2017-03-30 23:59:42552 url_filter_.SetDefaultFilteringBehavior(behavior);
bauerb5f8cda92015-10-07 15:36:44553
ericwilligers8b92b052016-10-19 22:21:58554 for (SupervisedUserServiceObserver& observer : observer_list_)
555 observer.OnURLFilterChanged();
bauerb5f8cda92015-10-07 15:36:44556}
557
treib9cc1b112016-01-08 10:08:01558void SupervisedUserService::OnSafeSitesSettingChanged() {
559 bool use_blacklist = supervised_users::IsSafeSitesBlacklistEnabled(profile_);
mmenkedb2637ff2017-03-30 23:59:42560 if (use_blacklist != url_filter_.HasBlacklist()) {
treib9cc1b112016-01-08 10:08:01561 if (use_blacklist && blacklist_state_ == BlacklistLoadState::NOT_LOADED) {
562 LoadBlacklist(GetBlacklistPath(), GURL(kBlacklistURL));
563 } else if (!use_blacklist ||
564 blacklist_state_ == BlacklistLoadState::LOADED) {
565 // Either the blacklist was turned off, or it was turned on but has
566 // already been loaded previously. Just update the setting.
567 UpdateBlacklist();
568 }
569 // Else: The blacklist was enabled, but the load is already in progress.
570 // Do nothing - we'll check the setting again when the load finishes.
571 }
572
573 bool use_online_check =
574 supervised_users::IsSafeSitesOnlineCheckEnabled(profile_);
mmenkedb2637ff2017-03-30 23:59:42575 if (use_online_check != url_filter_.HasAsyncURLChecker()) {
treib9cc1b112016-01-08 10:08:01576 if (use_online_check)
Mark Pilgrimb67362ed2018-05-15 15:59:47577 url_filter_.InitAsyncURLChecker(
578 content::BrowserContext::GetDefaultStoragePartition(profile_)
579 ->GetURLLoaderFactoryForBrowserProcess());
treib9cc1b112016-01-08 10:08:01580 else
mmenkedb2637ff2017-03-30 23:59:42581 url_filter_.ClearAsyncURLChecker();
treib9cc1b112016-01-08 10:08:01582 }
583}
584
bauerb5f8cda92015-10-07 15:36:44585void SupervisedUserService::OnSiteListsChanged(
586 const std::vector<scoped_refptr<SupervisedUserSiteList> >& site_lists) {
atanasova9572aaf2016-02-26 18:08:26587 whitelists_ = site_lists;
mmenkedb2637ff2017-03-30 23:59:42588 url_filter_.LoadWhitelists(site_lists);
bauerb5f8cda92015-10-07 15:36:44589}
590
591void SupervisedUserService::LoadBlacklist(const base::FilePath& path,
592 const GURL& url) {
treib9cc1b112016-01-08 10:08:01593 DCHECK(blacklist_state_ == BlacklistLoadState::NOT_LOADED);
594 blacklist_state_ = BlacklistLoadState::LOAD_STARTED;
fdoray9afc2bc2017-04-27 15:00:00595 base::PostTaskWithTraitsAndReplyWithResult(
bauerb5f8cda92015-10-07 15:36:44596 FROM_HERE,
Gabriel Charetteb10aeebc2018-07-26 20:15:00597 {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
fdoray4ad14932017-05-03 21:21:11598 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
fdoray9afc2bc2017-04-27 15:00:00599 base::BindOnce(&base::PathExists, path),
600 base::BindOnce(&SupervisedUserService::OnBlacklistFileChecked,
601 weak_ptr_factory_.GetWeakPtr(), path, url));
bauerb5f8cda92015-10-07 15:36:44602}
603
604void SupervisedUserService::OnBlacklistFileChecked(const base::FilePath& path,
605 const GURL& url,
606 bool file_exists) {
treib9cc1b112016-01-08 10:08:01607 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
bauerb5f8cda92015-10-07 15:36:44608 if (file_exists) {
609 LoadBlacklistFromFile(path);
610 return;
611 }
612
613 DCHECK(!blacklist_downloader_);
rhalavati5f1caa2b2017-02-25 08:22:16614
615 // Create traffic annotation tag.
616 net::NetworkTrafficAnnotationTag traffic_annotation =
617 net::DefineNetworkTrafficAnnotation("supervised_users_blacklist", R"(
618 semantics {
619 sender: "Supervised Users"
620 description:
621 "Downloads a static blacklist consisting of hostname hashes of "
622 "common inappropriate websites. This is only enabled for child "
623 "accounts and only if the corresponding setting is enabled by the "
624 "parent."
625 trigger:
626 "The file is downloaded on demand if the child account profile is "
627 "created and the setting is enabled."
628 data:
629 "No additional data is sent to the server beyond the request "
630 "itself."
631 destination: GOOGLE_OWNED_SERVICE
632 }
633 policy {
Ramin Halavati3b979782017-07-21 11:40:26634 cookies_allowed: NO
rhalavati5f1caa2b2017-02-25 08:22:16635 setting:
636 "The feature can be remotely enabled or disabled by the parent. In "
637 "addition, if sign-in is restricted to accounts from a managed "
638 "domain, those accounts are not going to be child accounts."
rhalavatieaa64e92017-04-03 09:36:43639 chrome_policy {
rhalavati5f1caa2b2017-02-25 08:22:16640 RestrictSigninToPattern {
641 policy_options {mode: MANDATORY}
rhalavatieaa64e92017-04-03 09:36:43642 RestrictSigninToPattern: "*@manageddomain.com"
rhalavati5f1caa2b2017-02-25 08:22:16643 }
644 }
645 })");
646
Mark Pilgrima8b7f432018-04-19 23:23:00647 auto factory = content::BrowserContext::GetDefaultStoragePartition(profile_)
648 ->GetURLLoaderFactoryForBrowserProcess();
bauerb5f8cda92015-10-07 15:36:44649 blacklist_downloader_.reset(new FileDownloader(
Mark Pilgrima8b7f432018-04-19 23:23:00650 url, path, false, std::move(factory),
Mark Pilgrimfa634c92018-06-19 20:01:24651 base::BindOnce(&SupervisedUserService::OnBlacklistDownloadDone,
652 base::Unretained(this), path),
rhalavati5f1caa2b2017-02-25 08:22:16653 traffic_annotation));
bauerb5f8cda92015-10-07 15:36:44654}
655
656void SupervisedUserService::LoadBlacklistFromFile(const base::FilePath& path) {
treib9cc1b112016-01-08 10:08:01657 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
658 blacklist_.ReadFromFile(
659 path,
660 base::Bind(&SupervisedUserService::OnBlacklistLoaded,
661 base::Unretained(this)));
bauerb5f8cda92015-10-07 15:36:44662}
663
treibf38cc252016-04-07 14:44:11664void SupervisedUserService::OnBlacklistDownloadDone(
665 const base::FilePath& path,
666 FileDownloader::Result result) {
treib9cc1b112016-01-08 10:08:01667 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
treibf38cc252016-04-07 14:44:11668 if (FileDownloader::IsSuccess(result)) {
bauerb5f8cda92015-10-07 15:36:44669 LoadBlacklistFromFile(path);
670 } else {
671 LOG(WARNING) << "Blacklist download failed";
treib9cc1b112016-01-08 10:08:01672 // TODO(treib): Retry downloading after some time?
bauerb5f8cda92015-10-07 15:36:44673 }
674 blacklist_downloader_.reset();
675}
676
677void SupervisedUserService::OnBlacklistLoaded() {
treib9cc1b112016-01-08 10:08:01678 DCHECK(blacklist_state_ == BlacklistLoadState::LOAD_STARTED);
679 blacklist_state_ = BlacklistLoadState::LOADED;
680 UpdateBlacklist();
681}
682
683void SupervisedUserService::UpdateBlacklist() {
684 bool use_blacklist = supervised_users::IsSafeSitesBlacklistEnabled(profile_);
mmenkedb2637ff2017-03-30 23:59:42685 url_filter_.SetBlacklist(use_blacklist ? &blacklist_ : nullptr);
ericwilligers8b92b052016-10-19 22:21:58686 for (SupervisedUserServiceObserver& observer : observer_list_)
687 observer.OnURLFilterChanged();
bauerb5f8cda92015-10-07 15:36:44688}
[email protected]acfcfbb2013-05-13 18:01:27689
[email protected]cce15bb2014-06-17 13:43:51690void SupervisedUserService::UpdateManualHosts() {
[email protected]cb1078de2013-12-23 20:04:22691 const base::DictionaryValue* dict =
[email protected]d20d0432014-06-12 17:14:05692 profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualHosts);
mmenkedb2637ff2017-03-30 23:59:42693 std::map<std::string, bool> host_map;
[email protected]cb1078de2013-12-23 20:04:22694 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
[email protected]5e022292013-02-06 16:42:17695 bool allow = false;
696 bool result = it.value().GetAsBoolean(&allow);
697 DCHECK(result);
mmenkedb2637ff2017-03-30 23:59:42698 host_map[it.key()] = allow;
[email protected]5e022292013-02-06 16:42:17699 }
mmenkedb2637ff2017-03-30 23:59:42700 url_filter_.SetManualHosts(std::move(host_map));
treibab0a39e2014-09-24 14:48:28701
ericwilligers8b92b052016-10-19 22:21:58702 for (SupervisedUserServiceObserver& observer : observer_list_)
703 observer.OnURLFilterChanged();
[email protected]0850e842013-01-19 03:44:31704}
705
[email protected]cce15bb2014-06-17 13:43:51706void SupervisedUserService::UpdateManualURLs() {
[email protected]cb1078de2013-12-23 20:04:22707 const base::DictionaryValue* dict =
[email protected]d20d0432014-06-12 17:14:05708 profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualURLs);
mmenkedb2637ff2017-03-30 23:59:42709 std::map<GURL, bool> url_map;
[email protected]cb1078de2013-12-23 20:04:22710 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
[email protected]5e022292013-02-06 16:42:17711 bool allow = false;
712 bool result = it.value().GetAsBoolean(&allow);
713 DCHECK(result);
mmenkedb2637ff2017-03-30 23:59:42714 url_map[GURL(it.key())] = allow;
[email protected]5e022292013-02-06 16:42:17715 }
mmenkedb2637ff2017-03-30 23:59:42716 url_filter_.SetManualURLs(std::move(url_map));
treibab0a39e2014-09-24 14:48:28717
ericwilligers8b92b052016-10-19 22:21:58718 for (SupervisedUserServiceObserver& observer : observer_list_)
719 observer.OnURLFilterChanged();
[email protected]0850e842013-01-19 03:44:31720}
[email protected]dfddd022013-07-10 17:29:48721
bauerbb519f8252016-05-13 09:16:39722void SupervisedUserService::OnForceSessionSyncChanged() {
723 includes_sync_sessions_type_ =
724 profile_->GetPrefs()->GetBoolean(prefs::kForceSessionSync);
bauerb5f8cda92015-10-07 15:36:44725 ProfileSyncServiceFactory::GetForProfile(profile_)
726 ->ReconfigureDatatypeManager();
727}
728
bauerb5f8cda92015-10-07 15:36:44729void SupervisedUserService::Shutdown() {
730 if (!did_init_)
731 return;
732 DCHECK(!did_shutdown_);
733 did_shutdown_ = true;
734 if (ProfileIsSupervised()) {
bratell0a7406f2017-03-28 07:46:37735 base::RecordAction(UserMetricsAction("ManagedUsers_QuitBrowser"));
bauerb5f8cda92015-10-07 15:36:44736 }
737 SetActive(false);
bauerb5f8cda92015-10-07 15:36:44738
maxbogue0a379452016-09-22 21:35:05739 browser_sync::ProfileSyncService* sync_service =
bauerb5f8cda92015-10-07 15:36:44740 ProfileSyncServiceFactory::GetForProfile(profile_);
bauerb5f8cda92015-10-07 15:36:44741 // Can be null in tests.
742 if (sync_service)
743 sync_service->RemovePreferenceProvider(this);
744}
745
brettw00899e62016-11-12 02:10:17746#if BUILDFLAG(ENABLE_EXTENSIONS)
mamir192d7882016-06-22 17:10:16747SupervisedUserService::ExtensionState SupervisedUserService::GetExtensionState(
mamire9609642016-06-28 22:17:54748 const Extension& extension) const {
749 bool was_installed_by_default = extension.was_installed_by_default();
mamir192d7882016-06-22 17:10:16750#if defined(OS_CHROMEOS)
751 // On Chrome OS all external sources are controlled by us so it means that
752 // they are "default". Method was_installed_by_default returns false because
753 // extensions creation flags are ignored in case of default extensions with
754 // update URL(the flags aren't passed to OnExternalExtensionUpdateUrlFound).
755 // TODO(dpolukhin): remove this Chrome OS specific code as soon as creation
756 // flags are not ignored.
757 was_installed_by_default =
mamire9609642016-06-28 22:17:54758 extensions::Manifest::IsExternalLocation(extension.location());
mamir192d7882016-06-22 17:10:16759#endif
760 // Note: Component extensions are protected from modification/uninstallation
761 // anyway, so there's no need to enforce them again for supervised users.
762 // Also, leave policy-installed extensions alone - they have their own
763 // management; in particular we don't want to override the force-install list.
mamire9609642016-06-28 22:17:54764 if (extensions::Manifest::IsComponentLocation(extension.location()) ||
765 extensions::Manifest::IsPolicyLocation(extension.location()) ||
766 extension.is_theme() || extension.from_bookmark() ||
767 extension.is_shared_module() || was_installed_by_default) {
768 return ExtensionState::ALLOWED;
mamir192d7882016-06-22 17:10:16769 }
770
mamire9609642016-06-28 22:17:54771 if (extensions::util::WasInstalledByCustodian(extension.id(), profile_))
772 return ExtensionState::FORCED;
mamir192d7882016-06-22 17:10:16773
mamire9609642016-06-28 22:17:54774 if (!base::FeatureList::IsEnabled(
775 supervised_users::kSupervisedUserInitiatedExtensionInstall)) {
776 return ExtensionState::BLOCKED;
777 }
778
779 auto extension_it = approved_extensions_map_.find(extension.id());
780 // If the installed version is approved, then the extension is allowed,
781 // otherwise, it requires approval.
782 if (extension_it != approved_extensions_map_.end() &&
Devlin Cronin03bf2d22017-12-20 08:21:05783 extension_it->second == extension.version()) {
mamire9609642016-06-28 22:17:54784 return ExtensionState::ALLOWED;
785 }
786 return ExtensionState::REQUIRE_APPROVAL;
mamir192d7882016-06-22 17:10:16787}
788
bauerb5f8cda92015-10-07 15:36:44789std::string SupervisedUserService::GetDebugPolicyProviderName() const {
790 // Save the string space in official builds.
Will Harris72a97a32018-05-29 19:05:21791#if DCHECK_IS_ON()
bauerb5f8cda92015-10-07 15:36:44792 return "Supervised User Service";
Will Harris72a97a32018-05-29 19:05:21793#else
794 IMMEDIATE_CRASH();
bauerb5f8cda92015-10-07 15:36:44795#endif
796}
797
mamire9609642016-06-28 22:17:54798bool SupervisedUserService::UserMayLoad(const Extension* extension,
bauerb5f8cda92015-10-07 15:36:44799 base::string16* error) const {
800 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:54801 ExtensionState result = GetExtensionState(*extension);
802 bool may_load = result != ExtensionState::BLOCKED;
bauerb5f8cda92015-10-07 15:36:44803 if (!may_load && error)
treib2170ea02015-10-13 14:55:12804 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:44805 return may_load;
806}
807
mamire9609642016-06-28 22:17:54808bool SupervisedUserService::UserMayModifySettings(const Extension* extension,
809 base::string16* error) const {
bauerb5f8cda92015-10-07 15:36:44810 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:54811 ExtensionState result = GetExtensionState(*extension);
812 // While the following check allows the supervised user to modify the settings
813 // and enable or disable the extension, MustRemainDisabled properly takes care
814 // of keeping an extension disabled when required.
815 // For custodian-installed extensions, the state is always FORCED, even if
816 // it's waiting for an update approval.
817 bool may_modify = result != ExtensionState::FORCED;
bauerb5f8cda92015-10-07 15:36:44818 if (!may_modify && error)
treib2170ea02015-10-13 14:55:12819 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:44820 return may_modify;
821}
822
823// Note: Having MustRemainInstalled always say "true" for custodian-installed
824// extensions does NOT prevent remote uninstalls (which is a bit unexpected, but
825// exactly what we want).
mamire9609642016-06-28 22:17:54826bool SupervisedUserService::MustRemainInstalled(const Extension* extension,
827 base::string16* error) const {
bauerb5f8cda92015-10-07 15:36:44828 DCHECK(ProfileIsSupervised());
mamire9609642016-06-28 22:17:54829 ExtensionState result = GetExtensionState(*extension);
830 bool may_not_uninstall = result == ExtensionState::FORCED;
bauerb5f8cda92015-10-07 15:36:44831 if (may_not_uninstall && error)
treib2170ea02015-10-13 14:55:12832 *error = GetExtensionsLockedMessage();
bauerb5f8cda92015-10-07 15:36:44833 return may_not_uninstall;
834}
835
Minh X. Nguyen45479012017-08-18 21:35:36836bool SupervisedUserService::MustRemainDisabled(
837 const Extension* extension,
838 extensions::disable_reason::DisableReason* reason,
839 base::string16* error) const {
mamire9609642016-06-28 22:17:54840 DCHECK(ProfileIsSupervised());
841 ExtensionState state = GetExtensionState(*extension);
842 // Only extensions that require approval should be disabled.
843 // Blocked extensions should be not loaded at all, and are taken care of
844 // at UserMayLoad.
845 bool must_remain_disabled = state == ExtensionState::REQUIRE_APPROVAL;
846
847 if (must_remain_disabled) {
848 if (error)
treib39ecc842016-11-17 12:07:07849 *error = GetExtensionsLockedMessage();
mamire9609642016-06-28 22:17:54850 // If the extension must remain disabled due to permission increase,
851 // then the update request has been already sent at update time.
852 // We do nothing and we don't add an extra disable reason.
853 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
854 if (extension_prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:36855 extension->id(),
856 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE)) {
mamire9609642016-06-28 22:17:54857 if (reason)
Minh X. Nguyen45479012017-08-18 21:35:36858 *reason = extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE;
mamire9609642016-06-28 22:17:54859 return true;
860 }
861 if (reason)
Minh X. Nguyen45479012017-08-18 21:35:36862 *reason = extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED;
mamire9609642016-06-28 22:17:54863 if (base::FeatureList::IsEnabled(
864 supervised_users::kSupervisedUserInitiatedExtensionInstall)) {
865 // If the Extension isn't pending a custodian approval already, send
866 // an approval request.
867 if (!extension_prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:36868 extension->id(), extensions::disable_reason::
869 DISABLE_CUSTODIAN_APPROVAL_REQUIRED)) {
mamire9609642016-06-28 22:17:54870 // MustRemainDisabled is a const method and hence cannot call
871 // AddExtensionInstallRequest directly.
872 SupervisedUserService* supervised_user_service =
873 SupervisedUserServiceFactory::GetForProfile(profile_);
874 supervised_user_service->AddExtensionInstallRequest(
Devlin Cronin03bf2d22017-12-20 08:21:05875 extension->id(), extension->version());
mamire9609642016-06-28 22:17:54876 }
877 }
878 }
879 return must_remain_disabled;
880}
881
882void SupervisedUserService::OnExtensionInstalled(
883 content::BrowserContext* browser_context,
884 const extensions::Extension* extension,
885 bool is_update) {
886 // This callback method is responsible for updating extension state and
887 // approved_extensions_map_ upon extension updates.
888 if (!is_update)
889 return;
890
891 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
892 const std::string& id = extension->id();
Devlin Cronin03bf2d22017-12-20 08:21:05893 const base::Version& version = extension->version();
mamire9609642016-06-28 22:17:54894
895 // If an already approved extension is updated without requiring
896 // new permissions, we update the approved_version.
897 if (!extension_prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:36898 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE) &&
mamire9609642016-06-28 22:17:54899 approved_extensions_map_.count(id) > 0 &&
900 approved_extensions_map_[id] < version) {
901 approved_extensions_map_[id] = version;
902
903 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
904 supervised_users::kApprovedExtensions, id);
905 std::unique_ptr<base::Value> version_value(
jdoerrie122c4da2017-03-06 11:12:04906 new base::Value(version.GetString()));
mamire9609642016-06-28 22:17:54907 GetSettingsService()->UpdateSetting(key, std::move(version_value));
908 }
909 // Upon extension update, the approved version may (or may not) match the
910 // installed one. Therefore, a change in extension state might be required.
911 ChangeExtensionStateIfNecessary(id);
912}
913
914void SupervisedUserService::UpdateApprovedExtensions() {
915 const base::DictionaryValue* dict = profile_->GetPrefs()->GetDictionary(
916 prefs::kSupervisedUserApprovedExtensions);
917 // Keep track of currently approved extensions. We may need to disable them if
918 // they are not in the approved map anymore.
919 std::set<std::string> extensions_to_be_checked;
920 for (const auto& extension : approved_extensions_map_)
921 extensions_to_be_checked.insert(extension.first);
922
923 approved_extensions_map_.clear();
924
925 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
926 std::string version_str;
927 bool result = it.value().GetAsString(&version_str);
928 DCHECK(result);
929 base::Version version(version_str);
930 if (version.IsValid()) {
931 approved_extensions_map_[it.key()] = version;
932 extensions_to_be_checked.insert(it.key());
933 } else {
934 LOG(WARNING) << "Invalid version number " << version_str;
935 }
936 }
937
938 for (const auto& extension_id : extensions_to_be_checked) {
939 ChangeExtensionStateIfNecessary(extension_id);
940 }
941}
942
943void SupervisedUserService::ChangeExtensionStateIfNecessary(
944 const std::string& extension_id) {
945 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
946 const Extension* extension = registry->GetInstalledExtension(extension_id);
947 // If the extension is not installed (yet), do nothing.
948 // Things will be handled after installation.
949 if (!extension)
950 return;
951
952 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
Devlin Cronin464a2672018-05-31 08:52:46953 extensions::ExtensionService* service =
mamire9609642016-06-28 22:17:54954 ExtensionSystem::Get(profile_)->extension_service();
955
956 ExtensionState state = GetExtensionState(*extension);
957 switch (state) {
958 // BLOCKED/FORCED extensions should be already disabled/enabled
959 // and we don't need to change their state here.
960 case ExtensionState::BLOCKED:
961 case ExtensionState::FORCED:
962 break;
963 case ExtensionState::REQUIRE_APPROVAL:
Minh X. Nguyen45479012017-08-18 21:35:36964 service->DisableExtension(
965 extension_id,
966 extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
mamire9609642016-06-28 22:17:54967 break;
968 case ExtensionState::ALLOWED:
969 extension_prefs->RemoveDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:36970 extension_id,
971 extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
mamire9609642016-06-28 22:17:54972 extension_prefs->RemoveDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:36973 extension_id,
974 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE);
mamire9609642016-06-28 22:17:54975 // If not disabled for other reasons, enable it.
976 if (extension_prefs->GetDisableReasons(extension_id) ==
Minh X. Nguyen45479012017-08-18 21:35:36977 extensions::disable_reason::DISABLE_NONE) {
mamire9609642016-06-28 22:17:54978 service->EnableExtension(extension_id);
979 }
980 break;
981 }
982}
983
bauerb5f8cda92015-10-07 15:36:44984void SupervisedUserService::SetExtensionsActive() {
985 extensions::ExtensionSystem* extension_system =
986 extensions::ExtensionSystem::Get(profile_);
987 extensions::ManagementPolicy* management_policy =
988 extension_system->management_policy();
989
990 if (management_policy) {
991 if (active_)
992 management_policy->RegisterProvider(this);
993 else
994 management_policy->UnregisterProvider(this);
995
996 // Re-check the policy to make sure any new settings get applied.
997 extension_system->extension_service()->CheckManagementPolicy();
998 }
999}
brettw00899e62016-11-12 02:10:171000#endif // BUILDFLAG(ENABLE_EXTENSIONS)
bauerb5f8cda92015-10-07 15:36:441001
1002syncer::ModelTypeSet SupervisedUserService::GetPreferredDataTypes() const {
1003 if (!ProfileIsSupervised())
1004 return syncer::ModelTypeSet();
1005
1006 syncer::ModelTypeSet result;
1007 if (IncludesSyncSessionsType())
1008 result.Put(syncer::SESSIONS);
1009 result.Put(syncer::EXTENSIONS);
1010 result.Put(syncer::EXTENSION_SETTINGS);
1011 result.Put(syncer::APPS);
1012 result.Put(syncer::APP_SETTINGS);
1013 result.Put(syncer::APP_NOTIFICATIONS);
1014 result.Put(syncer::APP_LIST);
1015 return result;
1016}
1017
jam1c5a91492016-02-24 20:47:531018#if !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:441019void SupervisedUserService::OnBrowserSetLastActive(Browser* browser) {
1020 bool profile_became_active = profile_->IsSameProfile(browser->profile());
1021 if (!is_profile_active_ && profile_became_active)
bratell0a7406f2017-03-28 07:46:371022 base::RecordAction(UserMetricsAction("ManagedUsers_OpenProfile"));
bauerb5f8cda92015-10-07 15:36:441023 else if (is_profile_active_ && !profile_became_active)
bratell0a7406f2017-03-28 07:46:371024 base::RecordAction(UserMetricsAction("ManagedUsers_SwitchProfile"));
bauerb5f8cda92015-10-07 15:36:441025
1026 is_profile_active_ = profile_became_active;
1027}
jam1c5a91492016-02-24 20:47:531028#endif // !defined(OS_ANDROID)
bauerb5f8cda92015-10-07 15:36:441029
1030void SupervisedUserService::OnSiteListUpdated() {
ericwilligers8b92b052016-10-19 22:21:581031 for (SupervisedUserServiceObserver& observer : observer_list_)
1032 observer.OnURLFilterChanged();
bauerb5f8cda92015-10-07 15:36:441033}