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/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/profiles/profile_helper.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/profiles/profile_manager.h"
24 #include "chrome/common/pref_names.h"
25 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_observer.h"
27 #include "content/public/browser/notification_registrar.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/notification_source.h"
34 static MagnificationManager* g_magnification_manager = NULL;
37 class MagnificationManagerImpl : public MagnificationManager,
38 public content::NotificationObserver,
39 public ash::SessionStateObserver {
41 MagnificationManagerImpl()
42 : first_time_update_(true),
44 magnifier_enabled_pref_handler_(
45 prefs::kAccessibilityScreenMagnifierEnabled),
46 magnifier_type_pref_handler_(prefs::kAccessibilityScreenMagnifierType),
47 magnifier_scale_pref_handler_(
48 prefs::kAccessibilityScreenMagnifierScale),
49 type_(ui::kDefaultMagnifierType),
52 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
53 content::NotificationService::AllSources());
55 chrome::NOTIFICATION_SESSION_STARTED,
56 content::NotificationService::AllSources());
58 chrome::NOTIFICATION_PROFILE_DESTROYED,
59 content::NotificationService::AllSources());
62 virtual ~MagnificationManagerImpl() {
63 CHECK(this == g_magnification_manager);
66 // MagnificationManager implimentation:
67 virtual bool IsMagnifierEnabled() const override {
71 virtual ui::MagnifierType GetMagnifierType() const override {
75 virtual void SetMagnifierEnabled(bool enabled) override {
79 PrefService* prefs = profile_->GetPrefs();
80 prefs->SetBoolean(prefs::kAccessibilityScreenMagnifierEnabled, enabled);
81 prefs->CommitPendingWrite();
84 virtual void SetMagnifierType(ui::MagnifierType type) override {
88 PrefService* prefs = profile_->GetPrefs();
89 prefs->SetInteger(prefs::kAccessibilityScreenMagnifierType, type);
90 prefs->CommitPendingWrite();
93 virtual void SaveScreenMagnifierScale(double scale) override {
97 profile_->GetPrefs()->SetDouble(prefs::kAccessibilityScreenMagnifierScale,
101 virtual double GetSavedScreenMagnifierScale() const override {
103 return std::numeric_limits<double>::min();
105 return profile_->GetPrefs()->GetDouble(
106 prefs::kAccessibilityScreenMagnifierScale);
109 virtual void SetProfileForTest(Profile* profile) override {
113 // SessionStateObserver overrides:
114 virtual void ActiveUserChanged(const std::string& user_id) override {
115 SetProfile(ProfileManager::GetActiveUserProfile());
119 void SetProfile(Profile* profile) {
120 pref_change_registrar_.reset();
123 // TODO(yoshiki): Move following code to PrefHandler.
124 pref_change_registrar_.reset(new PrefChangeRegistrar);
125 pref_change_registrar_->Init(profile->GetPrefs());
126 pref_change_registrar_->Add(
127 prefs::kAccessibilityScreenMagnifierEnabled,
128 base::Bind(&MagnificationManagerImpl::UpdateMagnifierFromPrefs,
129 base::Unretained(this)));
130 pref_change_registrar_->Add(
131 prefs::kAccessibilityScreenMagnifierType,
132 base::Bind(&MagnificationManagerImpl::UpdateMagnifierFromPrefs,
133 base::Unretained(this)));
136 magnifier_enabled_pref_handler_.HandleProfileChanged(profile_, profile);
137 magnifier_type_pref_handler_.HandleProfileChanged(profile_, profile);
138 magnifier_scale_pref_handler_.HandleProfileChanged(profile_, profile);
141 UpdateMagnifierFromPrefs();
144 virtual void SetMagnifierEnabledInternal(bool enabled) {
145 // This method may be invoked even when the other magnifier settings (e.g.
146 // type or scale) are changed, so we need to call magnification controller
147 // even if |enabled| is unchanged. Only if |enabled| is false and the
148 // magnifier is already disabled, we are sure that we don't need to reflect
149 // the new settings right now because the magnifier keeps disabled.
150 if (!enabled && !enabled_)
155 if (type_ == ui::MAGNIFIER_FULL) {
156 ash::Shell::GetInstance()->magnification_controller()->SetEnabled(
159 ash::Shell::GetInstance()->partial_magnification_controller()->SetEnabled(
164 virtual void SetMagnifierTypeInternal(ui::MagnifierType type) {
168 type_ = ui::MAGNIFIER_FULL; // (leave out for full magnifier)
171 void UpdateMagnifierFromPrefs() {
175 const bool enabled = profile_->GetPrefs()->GetBoolean(
176 prefs::kAccessibilityScreenMagnifierEnabled);
177 const int type_integer = profile_->GetPrefs()->GetInteger(
178 prefs::kAccessibilityScreenMagnifierType);
180 ui::MagnifierType type = ui::kDefaultMagnifierType;
181 if (type_integer > 0 && type_integer <= ui::kMaxMagnifierType) {
182 type = static_cast<ui::MagnifierType>(type_integer);
183 } else if (type_integer == 0) {
184 // Type 0 is used to disable the screen magnifier through policy. As the
185 // magnifier type is irrelevant in this case, it is OK to just fall back
192 SetMagnifierEnabledInternal(enabled);
193 SetMagnifierTypeInternal(type);
195 SetMagnifierTypeInternal(type);
196 SetMagnifierEnabledInternal(enabled);
199 AccessibilityStatusEventDetails details(
200 ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER,
203 ui::A11Y_NOTIFICATION_NONE);
205 #if defined(OS_CHROMEOS)
206 if (AccessibilityManager::Get()) {
207 AccessibilityManager::Get()->NotifyAccessibilityStatusChanged(details);
208 if (ash::Shell::GetInstance()) {
209 ash::Shell::GetInstance()->SetCursorCompositingEnabled(
210 AccessibilityManager::Get()->ShouldEnableCursorCompositing());
216 // content::NotificationObserver implementation:
217 virtual void Observe(int type,
218 const content::NotificationSource& source,
219 const content::NotificationDetails& details) override {
221 case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: {
222 // Update |profile_| when entering the login screen.
223 Profile* profile = ProfileManager::GetActiveUserProfile();
224 if (ProfileHelper::IsSigninProfile(profile))
228 case chrome::NOTIFICATION_SESSION_STARTED:
229 // Update |profile_| when entering a session.
230 SetProfile(ProfileManager::GetActiveUserProfile());
232 // Add a session state observer to be able to monitor session changes.
233 if (!session_state_observer_.get() && ash::Shell::HasInstance())
234 session_state_observer_.reset(
235 new ash::ScopedSessionStateObserver(this));
237 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
238 // Update |profile_| when exiting a session or shutting down.
239 Profile* profile = content::Source<Profile>(source).ptr();
240 if (profile_ == profile)
247 bool first_time_update_;
250 AccessibilityManager::PrefHandler magnifier_enabled_pref_handler_;
251 AccessibilityManager::PrefHandler magnifier_type_pref_handler_;
252 AccessibilityManager::PrefHandler magnifier_scale_pref_handler_;
254 ui::MagnifierType type_;
257 content::NotificationRegistrar registrar_;
258 scoped_ptr<PrefChangeRegistrar> pref_change_registrar_;
259 scoped_ptr<ash::ScopedSessionStateObserver> session_state_observer_;
261 DISALLOW_COPY_AND_ASSIGN(MagnificationManagerImpl);
265 void MagnificationManager::Initialize() {
266 CHECK(g_magnification_manager == NULL);
267 g_magnification_manager = new MagnificationManagerImpl();
271 void MagnificationManager::Shutdown() {
272 CHECK(g_magnification_manager);
273 delete g_magnification_manager;
274 g_magnification_manager = NULL;
278 MagnificationManager* MagnificationManager::Get() {
279 return g_magnification_manager;
282 } // namespace chromeos