// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/supervised_user/supervised_user_pref_store.h" #include <utility> #include <vector> #include "base/bind.h" #include "base/command_line.h" #include "base/values.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/supervised_user/supervised_user_bookmarks_handler.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_url_filter.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "components/bookmarks/common/bookmark_pref_names.h" #include "components/prefs/pref_value_map.h" #include "components/signin/core/common/signin_pref_names.h" #include "content/public/browser/notification_source.h" namespace { struct SupervisedUserSettingsPrefMappingEntry { const char* settings_name; const char* pref_name; }; SupervisedUserSettingsPrefMappingEntry kSupervisedUserSettingsPrefMapping[] = { { supervised_users::kContentPackDefaultFilteringBehavior, prefs::kDefaultSupervisedUserFilteringBehavior, }, { supervised_users::kContentPackManualBehaviorHosts, prefs::kSupervisedUserManualHosts, }, { supervised_users::kContentPackManualBehaviorURLs, prefs::kSupervisedUserManualURLs, }, { supervised_users::kForceSafeSearch, prefs::kForceGoogleSafeSearch, }, { supervised_users::kForceSafeSearch, prefs::kForceYouTubeSafetyMode, }, { supervised_users::kRecordHistory, prefs::kRecordHistory, }, { supervised_users::kSafeSitesEnabled, prefs::kSupervisedUserSafeSites, }, { supervised_users::kSigninAllowed, prefs::kSigninAllowed, }, { supervised_users::kUserName, prefs::kProfileName, }, }; } // namespace SupervisedUserPrefStore::SupervisedUserPrefStore( SupervisedUserSettingsService* supervised_user_settings_service) { user_settings_subscription_ = supervised_user_settings_service->Subscribe( base::Bind(&SupervisedUserPrefStore::OnNewSettingsAvailable, base::Unretained(this))); // Should only be nullptr in unit tests // TODO(peconn): Remove this once SupervisedUserPrefStore is (partially at // least) a KeyedService. The user_settings_subscription_ must be reset or // destroyed before the SupervisedUserSettingsService is. if (supervised_user_settings_service->GetProfile() != nullptr){ unsubscriber_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, content::Source<Profile>( supervised_user_settings_service->GetProfile())); } } bool SupervisedUserPrefStore::GetValue(const std::string& key, const base::Value** value) const { // TODO(bauerb): Temporary CHECK to force a clean crash while investigating // https://crbug.com/425785. Remove (or change back to DCHECK) once the bug // is fixed. CHECK(prefs_); return prefs_->GetValue(key, value); } void SupervisedUserPrefStore::AddObserver(PrefStore::Observer* observer) { observers_.AddObserver(observer); } void SupervisedUserPrefStore::RemoveObserver(PrefStore::Observer* observer) { observers_.RemoveObserver(observer); } bool SupervisedUserPrefStore::HasObservers() const { return observers_.might_have_observers(); } bool SupervisedUserPrefStore::IsInitializationComplete() const { return !!prefs_; } SupervisedUserPrefStore::~SupervisedUserPrefStore() { } void SupervisedUserPrefStore::OnNewSettingsAvailable( const base::DictionaryValue* settings) { scoped_ptr<PrefValueMap> old_prefs = std::move(prefs_); prefs_.reset(new PrefValueMap); if (settings) { // Set hardcoded prefs and defaults. prefs_->SetBoolean(prefs::kAllowDeletingBrowserHistory, false); prefs_->SetInteger(prefs::kDefaultSupervisedUserFilteringBehavior, SupervisedUserURLFilter::ALLOW); prefs_->SetBoolean(prefs::kForceGoogleSafeSearch, true); prefs_->SetBoolean(prefs::kForceYouTubeSafetyMode, true); prefs_->SetBoolean(prefs::kHideWebStoreIcon, true); prefs_->SetInteger(prefs::kIncognitoModeAvailability, IncognitoModePrefs::DISABLED); prefs_->SetBoolean(prefs::kRecordHistory, true); prefs_->SetBoolean(prefs::kSigninAllowed, false); // Copy supervised user settings to prefs. for (const auto& entry : kSupervisedUserSettingsPrefMapping) { const base::Value* value = NULL; if (settings->GetWithoutPathExpansion(entry.settings_name, &value)) prefs_->SetValue(entry.pref_name, value->CreateDeepCopy()); } // Manually set preferences that aren't direct copies of the settings value. bool record_history; if (settings->GetBoolean(supervised_users::kRecordHistory, &record_history)) { prefs_->SetBoolean(prefs::kAllowDeletingBrowserHistory, !record_history); prefs_->SetInteger(prefs::kIncognitoModeAvailability, record_history ? IncognitoModePrefs::DISABLED : IncognitoModePrefs::ENABLED); } if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableSupervisedUserManagedBookmarksFolder)) { // Reconstruct bookmarks from split settings. prefs_->SetValue( bookmarks::prefs::kSupervisedBookmarks, SupervisedUserBookmarksHandler::BuildBookmarksTree(*settings)); } } if (!old_prefs) { FOR_EACH_OBSERVER(Observer, observers_, OnInitializationCompleted(true)); return; } std::vector<std::string> changed_prefs; prefs_->GetDifferingKeys(old_prefs.get(), &changed_prefs); // Send out change notifications. for (const std::string& pref : changed_prefs) { FOR_EACH_OBSERVER(Observer, observers_, OnPrefValueChanged(pref)); } } // Callback to unsubscribe from the supervised user settings service. void SupervisedUserPrefStore::Observe( int type, const content::NotificationSource& src, const content::NotificationDetails& details) { DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type); user_settings_subscription_.reset(); }