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.
5 #include "chrome/browser/chromeos/accessibility/magnification_manager.h"
9 #include "ash/magnifier/magnification_controller.h"
10 #include "ash/magnifier/partial_magnification_controller.h"
11 #include "ash/session_state_delegate.h"
12 #include "ash/shell.h"
13 #include "ash/shell_delegate.h"
14 #include "ash/system/tray/system_tray_notifier.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/singleton.h"
17 #include "base/prefs/pref_member.h"
18 #include "base/prefs/pref_service.h"
19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
21 #include "chrome/browser/chromeos/login/user_manager.h"
22 #include "chrome/browser/chromeos/profiles/profile_helper.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/profiles/profile_manager.h"
25 #include "chrome/common/pref_names.h"
26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_observer.h"
28 #include "content/public/browser/notification_registrar.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/notification_source.h"
35 static MagnificationManager
* g_magnification_manager
= NULL
;
38 class MagnificationManagerImpl
: public MagnificationManager
,
39 public content::NotificationObserver
,
40 public ash::SessionStateObserver
{
42 MagnificationManagerImpl()
43 : first_time_update_(true),
45 magnifier_enabled_pref_handler_(prefs::kScreenMagnifierEnabled
),
46 magnifier_type_pref_handler_(prefs::kScreenMagnifierType
),
47 magnifier_scale_pref_handler_(prefs::kScreenMagnifierScale
),
48 type_(ash::kDefaultMagnifierType
),
51 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
,
52 content::NotificationService::AllSources());
54 chrome::NOTIFICATION_SESSION_STARTED
,
55 content::NotificationService::AllSources());
57 chrome::NOTIFICATION_PROFILE_DESTROYED
,
58 content::NotificationService::AllSources());
61 virtual ~MagnificationManagerImpl() {
62 CHECK(this == g_magnification_manager
);
65 // MagnificationManager implimentation:
66 virtual bool IsMagnifierEnabled() const OVERRIDE
{
70 virtual ash::MagnifierType
GetMagnifierType() const OVERRIDE
{
74 virtual void SetMagnifierEnabled(bool enabled
) OVERRIDE
{
78 PrefService
* prefs
= profile_
->GetPrefs();
79 prefs
->SetBoolean(prefs::kScreenMagnifierEnabled
, enabled
);
80 prefs
->CommitPendingWrite();
83 virtual void SetMagnifierType(ash::MagnifierType type
) OVERRIDE
{
87 PrefService
* prefs
= profile_
->GetPrefs();
88 prefs
->SetInteger(prefs::kScreenMagnifierType
, type
);
89 prefs
->CommitPendingWrite();
92 virtual void SaveScreenMagnifierScale(double scale
) OVERRIDE
{
96 profile_
->GetPrefs()->SetDouble(prefs::kScreenMagnifierScale
, scale
);
99 virtual double GetSavedScreenMagnifierScale() const OVERRIDE
{
101 return std::numeric_limits
<double>::min();
103 return profile_
->GetPrefs()->GetDouble(prefs::kScreenMagnifierScale
);
106 virtual void SetProfileForTest(Profile
* profile
) OVERRIDE
{
110 // SessionStateObserver overrides:
111 virtual void ActiveUserChanged(const std::string
& user_id
) OVERRIDE
{
112 SetProfile(ProfileManager::GetActiveUserProfile());
116 void SetProfile(Profile
* profile
) {
117 pref_change_registrar_
.reset();
120 // TODO(yoshiki): Move following code to PrefHandler.
121 pref_change_registrar_
.reset(new PrefChangeRegistrar
);
122 pref_change_registrar_
->Init(profile
->GetPrefs());
123 pref_change_registrar_
->Add(
124 prefs::kScreenMagnifierEnabled
,
125 base::Bind(&MagnificationManagerImpl::UpdateMagnifierFromPrefs
,
126 base::Unretained(this)));
127 pref_change_registrar_
->Add(
128 prefs::kScreenMagnifierType
,
129 base::Bind(&MagnificationManagerImpl::UpdateMagnifierFromPrefs
,
130 base::Unretained(this)));
133 magnifier_enabled_pref_handler_
.HandleProfileChanged(profile_
, profile
);
134 magnifier_type_pref_handler_
.HandleProfileChanged(profile_
, profile
);
135 magnifier_scale_pref_handler_
.HandleProfileChanged(profile_
, profile
);
138 UpdateMagnifierFromPrefs();
141 virtual void SetMagnifierEnabledInternal(bool enabled
) {
142 // This method may be invoked even when the other magnifier settings (e.g.
143 // type or scale) are changed, so we need to call magnification controller
144 // even if |enabled| is unchanged. Only if |enabled| is false and the
145 // magnifier is already disabled, we are sure that we don't need to reflect
146 // the new settings right now because the magnifier keeps disabled.
147 if (!enabled
&& !enabled_
)
152 if (type_
== ash::MAGNIFIER_FULL
) {
153 ash::Shell::GetInstance()->magnification_controller()->SetEnabled(
156 ash::Shell::GetInstance()->partial_magnification_controller()->SetEnabled(
161 virtual void SetMagnifierTypeInternal(ash::MagnifierType type
) {
165 type_
= ash::MAGNIFIER_FULL
; // (leave out for full magnifier)
168 void UpdateMagnifierFromPrefs() {
173 profile_
->GetPrefs()->GetBoolean(prefs::kScreenMagnifierEnabled
);
174 const int type_integer
=
175 profile_
->GetPrefs()->GetInteger(prefs::kScreenMagnifierType
);
177 ash::MagnifierType type
= ash::kDefaultMagnifierType
;
178 if (type_integer
> 0 && type_integer
<= ash::kMaxMagnifierType
) {
179 type
= static_cast<ash::MagnifierType
>(type_integer
);
180 } else if (type_integer
== 0) {
181 // Type 0 is used to disable the screen magnifier through policy. As the
182 // magnifier type is irrelevant in this case, it is OK to just fall back
189 SetMagnifierEnabledInternal(enabled
);
190 SetMagnifierTypeInternal(type
);
192 SetMagnifierTypeInternal(type
);
193 SetMagnifierEnabledInternal(enabled
);
196 AccessibilityStatusEventDetails
details(
197 ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER
,
200 ash::A11Y_NOTIFICATION_NONE
);
202 #if defined(OS_CHROMEOS)
203 if (AccessibilityManager::Get()) {
204 AccessibilityManager::Get()->NotifyAccessibilityStatusChanged(details
);
205 if (ash::Shell::GetInstance()) {
206 ash::Shell::GetInstance()->SetCursorCompositingEnabled(
207 AccessibilityManager::Get()->ShouldEnableCursorCompositing());
213 // content::NotificationObserver implementation:
214 virtual void Observe(int type
,
215 const content::NotificationSource
& source
,
216 const content::NotificationDetails
& details
) OVERRIDE
{
218 case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
: {
219 // Update |profile_| when entering the login screen.
220 Profile
* profile
= ProfileManager::GetActiveUserProfile();
221 if (ProfileHelper::IsSigninProfile(profile
))
225 case chrome::NOTIFICATION_SESSION_STARTED
:
226 // Update |profile_| when entering a session.
227 SetProfile(ProfileManager::GetActiveUserProfile());
229 // Add a session state observer to be able to monitor session changes.
230 if (!session_state_observer_
.get() && ash::Shell::HasInstance())
231 session_state_observer_
.reset(
232 new ash::ScopedSessionStateObserver(this));
234 case chrome::NOTIFICATION_PROFILE_DESTROYED
: {
235 // Update |profile_| when exiting a session or shutting down.
236 Profile
* profile
= content::Source
<Profile
>(source
).ptr();
237 if (profile_
== profile
)
244 bool first_time_update_
;
247 AccessibilityManager::PrefHandler magnifier_enabled_pref_handler_
;
248 AccessibilityManager::PrefHandler magnifier_type_pref_handler_
;
249 AccessibilityManager::PrefHandler magnifier_scale_pref_handler_
;
251 ash::MagnifierType type_
;
254 content::NotificationRegistrar registrar_
;
255 scoped_ptr
<PrefChangeRegistrar
> pref_change_registrar_
;
256 scoped_ptr
<ash::ScopedSessionStateObserver
> session_state_observer_
;
258 DISALLOW_COPY_AND_ASSIGN(MagnificationManagerImpl
);
262 void MagnificationManager::Initialize() {
263 CHECK(g_magnification_manager
== NULL
);
264 g_magnification_manager
= new MagnificationManagerImpl();
268 void MagnificationManager::Shutdown() {
269 CHECK(g_magnification_manager
);
270 delete g_magnification_manager
;
271 g_magnification_manager
= NULL
;
275 MagnificationManager
* MagnificationManager::Get() {
276 return g_magnification_manager
;
279 } // namespace chromeos