1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/chromeos/policy/recommendation_restorer.h" 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/shell.h" 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/wm/user_activity_detector.h" 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/bind.h" 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/bind_helpers.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/location.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/logging.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/prefs/pref_service.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/values.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/chromeos/profiles/profile_helper.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/profiles/profile.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/pref_names.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/notification_details.h" 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/notification_service.h" 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/notification_source.h" 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace policy { 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The amount of idle time after which recommended values are restored. 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kRestoreDelayInMs = 60 * 1000; // 1 minute. 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochRecommendationRestorer::RecommendationRestorer(Profile* profile) 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : logged_in_(false) { 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!chromeos::ProfileHelper::IsSigninProfile(profile)) 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pref_change_registrar_.Init(profile->GetPrefs()); 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pref_change_registrar_.Add(prefs::kLargeCursorEnabled, 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&RecommendationRestorer::Restore, 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this), true)); 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pref_change_registrar_.Add(prefs::kSpokenFeedbackEnabled, 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&RecommendationRestorer::Restore, 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this), true)); 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pref_change_registrar_.Add(prefs::kHighContrastEnabled, 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&RecommendationRestorer::Restore, 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this), true)); 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pref_change_registrar_.Add(prefs::kScreenMagnifierEnabled, 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&RecommendationRestorer::Restore, 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this), true)); 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pref_change_registrar_.Add(prefs::kScreenMagnifierType, 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&RecommendationRestorer::Restore, 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this), true)); 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch notification_registrar_.Add(this, chrome::NOTIFICATION_LOGIN_USER_CHANGED, 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::NotificationService::AllSources()); 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RestoreAll(); 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochRecommendationRestorer::~RecommendationRestorer() { 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RecommendationRestorer::Shutdown() { 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StopTimer(); 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pref_change_registrar_.RemoveAll(); 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch notification_registrar_.RemoveAll(); 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RecommendationRestorer::Observe( 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int type, 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const content::NotificationSource& source, 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const content::NotificationDetails& details) { 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) { 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch logged_in_ = true; 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch notification_registrar_.RemoveAll(); 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StopTimer(); 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RestoreAll(); 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid RecommendationRestorer::OnUserActivity(const ui::Event* event) { 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (restore_timer_.IsRunning()) 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch restore_timer_.Reset(); 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RecommendationRestorer::Restore(bool allow_delay, 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& pref_name) { 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const PrefService::Preference* pref = 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pref_change_registrar_.prefs()->FindPreference(pref_name.c_str()); 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!pref) { 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!pref->GetRecommendedValue() || !pref->HasUserSetting()) 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (logged_in_) { 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch allow_delay = false; 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (allow_delay && ash::Shell::HasInstance()) { 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Skip the delay if there has been no user input since the browser started. 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const ash::UserActivityDetector* user_activity_detector = 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ash::Shell::GetInstance()->user_activity_detector(); 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch allow_delay = !user_activity_detector->last_activity_time().is_null(); 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (allow_delay) 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StartTimer(); 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pref_change_registrar_.prefs()->ClearPref(pref->name().c_str()); 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RecommendationRestorer::RestoreAll() { 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Restore(false, prefs::kLargeCursorEnabled); 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Restore(false, prefs::kSpokenFeedbackEnabled); 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Restore(false, prefs::kHighContrastEnabled); 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Restore(false, prefs::kScreenMagnifierEnabled); 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Restore(false, prefs::kScreenMagnifierType); 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RecommendationRestorer::StartTimer() { 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Listen for user activity so that the timer can be reset while the user is 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // active, causing it to fire only when the user remains idle for 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // |kRestoreDelayInMs|. 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (ash::Shell::HasInstance()) { 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ash::UserActivityDetector* user_activity_detector = 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ash::Shell::GetInstance()->user_activity_detector(); 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!user_activity_detector->HasObserver(this)) 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch user_activity_detector->AddObserver(this); 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // There should be a separate timer for each pref. However, in the common 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // case of the user changing settings, a single timer is sufficient. This is 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // because a change initiated by the user implies user activity, so that even 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // if there was a separate timer per pref, they would all be reset at that 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // point, causing them to fire at exactly the same time. In the much rarer 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // case of a recommended value changing, a single timer is a close 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // approximation of the behavior that would be obtained by resetting the timer 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // for the affected pref only. 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch restore_timer_.Start(FROM_HERE, 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeDelta::FromMilliseconds(kRestoreDelayInMs), 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&RecommendationRestorer::RestoreAll, 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this))); 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RecommendationRestorer::StopTimer() { 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch restore_timer_.Stop(); 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (ash::Shell::HasInstance()) 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this); 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace policy 154