Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / chromeos / accessibility / magnification_manager.cc
blobb714bc5f6931097cd69dcd558080510fab74b50d
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"
7 #include <limits>
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/focused_node_details.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"
32 namespace chromeos {
34 namespace {
35 static MagnificationManager* g_magnification_manager = NULL;
38 class MagnificationManagerImpl : public MagnificationManager,
39 public content::NotificationObserver,
40 public ash::SessionStateObserver {
41 public:
42 MagnificationManagerImpl()
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 observing_focus_change_in_page_(false) {
52 registrar_.Add(this,
53 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
54 content::NotificationService::AllSources());
55 registrar_.Add(this,
56 chrome::NOTIFICATION_SESSION_STARTED,
57 content::NotificationService::AllSources());
58 registrar_.Add(this,
59 chrome::NOTIFICATION_PROFILE_DESTROYED,
60 content::NotificationService::AllSources());
63 ~MagnificationManagerImpl() override {
64 CHECK(this == g_magnification_manager);
67 // MagnificationManager implimentation:
68 bool IsMagnifierEnabled() const override { return enabled_; }
70 ui::MagnifierType GetMagnifierType() const override { return type_; }
72 void SetMagnifierEnabled(bool enabled) override {
73 if (!profile_)
74 return;
76 PrefService* prefs = profile_->GetPrefs();
77 prefs->SetBoolean(prefs::kAccessibilityScreenMagnifierEnabled, enabled);
78 prefs->CommitPendingWrite();
81 void SetMagnifierType(ui::MagnifierType type) override {
82 if (!profile_)
83 return;
85 PrefService* prefs = profile_->GetPrefs();
86 prefs->SetInteger(prefs::kAccessibilityScreenMagnifierType, type);
87 prefs->CommitPendingWrite();
90 void SaveScreenMagnifierScale(double scale) override {
91 if (!profile_)
92 return;
94 profile_->GetPrefs()->SetDouble(prefs::kAccessibilityScreenMagnifierScale,
95 scale);
98 double GetSavedScreenMagnifierScale() const override {
99 if (!profile_)
100 return std::numeric_limits<double>::min();
102 return profile_->GetPrefs()->GetDouble(
103 prefs::kAccessibilityScreenMagnifierScale);
106 void SetProfileForTest(Profile* profile) override { SetProfile(profile); }
108 // SessionStateObserver overrides:
109 void ActiveUserChanged(const std::string& user_id) override {
110 SetProfile(ProfileManager::GetActiveUserProfile());
113 private:
114 void SetProfile(Profile* profile) {
115 pref_change_registrar_.reset();
117 if (profile) {
118 // TODO(yoshiki): Move following code to PrefHandler.
119 pref_change_registrar_.reset(new PrefChangeRegistrar);
120 pref_change_registrar_->Init(profile->GetPrefs());
121 pref_change_registrar_->Add(
122 prefs::kAccessibilityScreenMagnifierEnabled,
123 base::Bind(&MagnificationManagerImpl::UpdateMagnifierFromPrefs,
124 base::Unretained(this)));
125 pref_change_registrar_->Add(
126 prefs::kAccessibilityScreenMagnifierType,
127 base::Bind(&MagnificationManagerImpl::UpdateMagnifierFromPrefs,
128 base::Unretained(this)));
131 magnifier_enabled_pref_handler_.HandleProfileChanged(profile_, profile);
132 magnifier_type_pref_handler_.HandleProfileChanged(profile_, profile);
133 magnifier_scale_pref_handler_.HandleProfileChanged(profile_, profile);
135 profile_ = profile;
136 UpdateMagnifierFromPrefs();
139 virtual void SetMagnifierEnabledInternal(bool enabled) {
140 // This method may be invoked even when the other magnifier settings (e.g.
141 // type or scale) are changed, so we need to call magnification controller
142 // even if |enabled| is unchanged. Only if |enabled| is false and the
143 // magnifier is already disabled, we are sure that we don't need to reflect
144 // the new settings right now because the magnifier keeps disabled.
145 if (!enabled && !enabled_)
146 return;
148 enabled_ = enabled;
150 if (type_ == ui::MAGNIFIER_FULL) {
151 ash::Shell::GetInstance()->magnification_controller()->SetEnabled(
152 enabled_);
153 MonitorFocusInPageChange();
154 } else {
155 ash::Shell::GetInstance()->partial_magnification_controller()->SetEnabled(
156 enabled_);
160 virtual void SetMagnifierTypeInternal(ui::MagnifierType type) {
161 if (type_ == type)
162 return;
164 type_ = ui::MAGNIFIER_FULL; // (leave out for full magnifier)
167 void UpdateMagnifierFromPrefs() {
168 if (!profile_)
169 return;
171 const bool enabled = profile_->GetPrefs()->GetBoolean(
172 prefs::kAccessibilityScreenMagnifierEnabled);
173 const int type_integer = profile_->GetPrefs()->GetInteger(
174 prefs::kAccessibilityScreenMagnifierType);
176 ui::MagnifierType type = ui::kDefaultMagnifierType;
177 if (type_integer > 0 && type_integer <= ui::kMaxMagnifierType) {
178 type = static_cast<ui::MagnifierType>(type_integer);
179 } else if (type_integer == 0) {
180 // Type 0 is used to disable the screen magnifier through policy. As the
181 // magnifier type is irrelevant in this case, it is OK to just fall back
182 // to the default.
183 } else {
184 NOTREACHED();
187 if (!enabled) {
188 SetMagnifierEnabledInternal(enabled);
189 SetMagnifierTypeInternal(type);
190 } else {
191 SetMagnifierTypeInternal(type);
192 SetMagnifierEnabledInternal(enabled);
195 AccessibilityStatusEventDetails details(
196 ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER,
197 enabled_,
198 type_,
199 ui::A11Y_NOTIFICATION_NONE);
201 if (AccessibilityManager::Get()) {
202 AccessibilityManager::Get()->NotifyAccessibilityStatusChanged(details);
203 if (ash::Shell::GetInstance()) {
204 ash::Shell::GetInstance()->SetCursorCompositingEnabled(
205 AccessibilityManager::Get()->ShouldEnableCursorCompositing());
210 void MonitorFocusInPageChange() {
211 if (enabled_ && !observing_focus_change_in_page_) {
212 registrar_.Add(this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
213 content::NotificationService::AllSources());
214 observing_focus_change_in_page_ = true;
215 } else if (!enabled_ && observing_focus_change_in_page_) {
216 registrar_.Remove(this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
217 content::NotificationService::AllSources());
218 observing_focus_change_in_page_ = false;
222 // content::NotificationObserver implementation:
223 void Observe(int type,
224 const content::NotificationSource& source,
225 const content::NotificationDetails& details) override {
226 switch (type) {
227 case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: {
228 // Update |profile_| when entering the login screen.
229 Profile* profile = ProfileManager::GetActiveUserProfile();
230 if (ProfileHelper::IsSigninProfile(profile))
231 SetProfile(profile);
232 break;
234 case chrome::NOTIFICATION_SESSION_STARTED:
235 // Update |profile_| when entering a session.
236 SetProfile(ProfileManager::GetActiveUserProfile());
238 // Add a session state observer to be able to monitor session changes.
239 if (!session_state_observer_.get() && ash::Shell::HasInstance())
240 session_state_observer_.reset(
241 new ash::ScopedSessionStateObserver(this));
242 break;
243 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
244 // Update |profile_| when exiting a session or shutting down.
245 Profile* profile = content::Source<Profile>(source).ptr();
246 if (profile_ == profile)
247 SetProfile(NULL);
248 break;
250 case content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE: {
251 content::FocusedNodeDetails* node_details =
252 content::Details<content::FocusedNodeDetails>(details).ptr();
253 ash::Shell::GetInstance()
254 ->magnification_controller()
255 ->HandleFocusedNodeChanged(node_details->is_editable_node,
256 node_details->node_bounds_in_screen);
257 break;
262 Profile* profile_;
264 AccessibilityManager::PrefHandler magnifier_enabled_pref_handler_;
265 AccessibilityManager::PrefHandler magnifier_type_pref_handler_;
266 AccessibilityManager::PrefHandler magnifier_scale_pref_handler_;
268 ui::MagnifierType type_;
269 bool enabled_;
270 bool observing_focus_change_in_page_;
272 content::NotificationRegistrar registrar_;
273 scoped_ptr<PrefChangeRegistrar> pref_change_registrar_;
274 scoped_ptr<ash::ScopedSessionStateObserver> session_state_observer_;
276 DISALLOW_COPY_AND_ASSIGN(MagnificationManagerImpl);
279 // static
280 void MagnificationManager::Initialize() {
281 CHECK(g_magnification_manager == NULL);
282 g_magnification_manager = new MagnificationManagerImpl();
285 // static
286 void MagnificationManager::Shutdown() {
287 CHECK(g_magnification_manager);
288 delete g_magnification_manager;
289 g_magnification_manager = NULL;
292 // static
293 MagnificationManager* MagnificationManager::Get() {
294 return g_magnification_manager;
297 } // namespace chromeos