Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / accessibility / magnification_manager.cc
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.
4
5 #include "chrome/browser/chromeos/accessibility/magnification_manager.h"
6
7 #include <limits>
8
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"
30
31 namespace chromeos {
32
33 namespace {
34 static MagnificationManager* g_magnification_manager = NULL;
35 }
36
37 class MagnificationManagerImpl : public MagnificationManager,
38                                  public content::NotificationObserver,
39                                  public ash::SessionStateObserver {
40  public:
41   MagnificationManagerImpl()
42       : first_time_update_(true),
43         profile_(NULL),
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),
50         enabled_(false) {
51     registrar_.Add(this,
52                    chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
53                    content::NotificationService::AllSources());
54     registrar_.Add(this,
55                    chrome::NOTIFICATION_SESSION_STARTED,
56                    content::NotificationService::AllSources());
57     registrar_.Add(this,
58                    chrome::NOTIFICATION_PROFILE_DESTROYED,
59                    content::NotificationService::AllSources());
60   }
61
62   virtual ~MagnificationManagerImpl() {
63     CHECK(this == g_magnification_manager);
64   }
65
66   // MagnificationManager implimentation:
67   virtual bool IsMagnifierEnabled() const override {
68     return enabled_;
69   }
70
71   virtual ui::MagnifierType GetMagnifierType() const override {
72     return type_;
73   }
74
75   virtual void SetMagnifierEnabled(bool enabled) override {
76     if (!profile_)
77       return;
78
79     PrefService* prefs = profile_->GetPrefs();
80     prefs->SetBoolean(prefs::kAccessibilityScreenMagnifierEnabled, enabled);
81     prefs->CommitPendingWrite();
82   }
83
84   virtual void SetMagnifierType(ui::MagnifierType type) override {
85     if (!profile_)
86       return;
87
88     PrefService* prefs = profile_->GetPrefs();
89     prefs->SetInteger(prefs::kAccessibilityScreenMagnifierType, type);
90     prefs->CommitPendingWrite();
91   }
92
93   virtual void SaveScreenMagnifierScale(double scale) override {
94     if (!profile_)
95       return;
96
97     profile_->GetPrefs()->SetDouble(prefs::kAccessibilityScreenMagnifierScale,
98                                     scale);
99   }
100
101   virtual double GetSavedScreenMagnifierScale() const override {
102     if (!profile_)
103       return std::numeric_limits<double>::min();
104
105     return profile_->GetPrefs()->GetDouble(
106         prefs::kAccessibilityScreenMagnifierScale);
107   }
108
109   virtual void SetProfileForTest(Profile* profile) override {
110     SetProfile(profile);
111   }
112
113   // SessionStateObserver overrides:
114   virtual void ActiveUserChanged(const std::string& user_id) override {
115     SetProfile(ProfileManager::GetActiveUserProfile());
116   }
117
118  private:
119   void SetProfile(Profile* profile) {
120     pref_change_registrar_.reset();
121
122     if (profile) {
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)));
134     }
135
136     magnifier_enabled_pref_handler_.HandleProfileChanged(profile_, profile);
137     magnifier_type_pref_handler_.HandleProfileChanged(profile_, profile);
138     magnifier_scale_pref_handler_.HandleProfileChanged(profile_, profile);
139
140     profile_ = profile;
141     UpdateMagnifierFromPrefs();
142   }
143
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_)
151       return;
152
153     enabled_ = enabled;
154
155     if (type_ == ui::MAGNIFIER_FULL) {
156       ash::Shell::GetInstance()->magnification_controller()->SetEnabled(
157           enabled_);
158     } else {
159       ash::Shell::GetInstance()->partial_magnification_controller()->SetEnabled(
160           enabled_);
161     }
162   }
163
164   virtual void SetMagnifierTypeInternal(ui::MagnifierType type) {
165     if (type_ == type)
166       return;
167
168     type_ = ui::MAGNIFIER_FULL;  // (leave out for full magnifier)
169   }
170
171   void UpdateMagnifierFromPrefs() {
172     if (!profile_)
173       return;
174
175     const bool enabled = profile_->GetPrefs()->GetBoolean(
176         prefs::kAccessibilityScreenMagnifierEnabled);
177     const int type_integer = profile_->GetPrefs()->GetInteger(
178         prefs::kAccessibilityScreenMagnifierType);
179
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
186       // to the default.
187     } else {
188       NOTREACHED();
189     }
190
191     if (!enabled) {
192       SetMagnifierEnabledInternal(enabled);
193       SetMagnifierTypeInternal(type);
194     } else {
195       SetMagnifierTypeInternal(type);
196       SetMagnifierEnabledInternal(enabled);
197     }
198
199     AccessibilityStatusEventDetails details(
200         ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER,
201         enabled_,
202         type_,
203         ui::A11Y_NOTIFICATION_NONE);
204
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());
211       }
212     }
213 #endif
214   }
215
216   // content::NotificationObserver implementation:
217   virtual void Observe(int type,
218                        const content::NotificationSource& source,
219                        const content::NotificationDetails& details) override {
220     switch (type) {
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))
225           SetProfile(profile);
226         break;
227       }
228       case chrome::NOTIFICATION_SESSION_STARTED:
229         // Update |profile_| when entering a session.
230         SetProfile(ProfileManager::GetActiveUserProfile());
231
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));
236         break;
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)
241           SetProfile(NULL);
242         break;
243       }
244     }
245   }
246
247   bool first_time_update_;
248   Profile* profile_;
249
250   AccessibilityManager::PrefHandler magnifier_enabled_pref_handler_;
251   AccessibilityManager::PrefHandler magnifier_type_pref_handler_;
252   AccessibilityManager::PrefHandler magnifier_scale_pref_handler_;
253
254   ui::MagnifierType type_;
255   bool enabled_;
256
257   content::NotificationRegistrar registrar_;
258   scoped_ptr<PrefChangeRegistrar> pref_change_registrar_;
259   scoped_ptr<ash::ScopedSessionStateObserver> session_state_observer_;
260
261   DISALLOW_COPY_AND_ASSIGN(MagnificationManagerImpl);
262 };
263
264 // static
265 void MagnificationManager::Initialize() {
266   CHECK(g_magnification_manager == NULL);
267   g_magnification_manager = new MagnificationManagerImpl();
268 }
269
270 // static
271 void MagnificationManager::Shutdown() {
272   CHECK(g_magnification_manager);
273   delete g_magnification_manager;
274   g_magnification_manager = NULL;
275 }
276
277 // static
278 MagnificationManager* MagnificationManager::Get() {
279   return g_magnification_manager;
280 }
281
282 }  // namespace chromeos