1 // Copyright (c) 2013 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/ui/gesture_prefs_observer_factory_aura.h"
10 #include "base/bind_helpers.h"
11 #include "base/compiler_specific.h"
12 #include "base/prefs/pref_change_registrar.h"
13 #include "base/prefs/pref_service.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/profiles/incognito_helpers.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/pref_names.h"
18 #include "components/keyed_service/content/browser_context_dependency_manager.h"
19 #include "components/pref_registry/pref_registry_syncable.h"
20 #include "content/public/browser/notification_observer.h"
21 #include "content/public/browser/notification_service.h"
22 #include "content/public/browser/overscroll_configuration.h"
23 #include "content/public/common/renderer_preferences.h"
24 #include "ui/events/gestures/gesture_configuration.h"
26 using ui::GestureConfiguration
;
30 struct OverscrollPref
{
31 const char* pref_name
;
32 content::OverscrollConfig config
;
35 const std::vector
<OverscrollPref
>& GetOverscrollPrefs() {
36 CR_DEFINE_STATIC_LOCAL(std::vector
<OverscrollPref
>, overscroll_prefs
, ());
37 if (overscroll_prefs
.empty()) {
38 using namespace content
;
39 const OverscrollPref kOverscrollPrefs
[] = {
40 { prefs::kOverscrollHorizontalThresholdComplete
,
41 OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE
},
42 { prefs::kOverscrollVerticalThresholdComplete
,
43 OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE
},
44 { prefs::kOverscrollMinimumThresholdStart
,
45 OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN
},
46 { prefs::kOverscrollMinimumThresholdStartTouchpad
,
47 OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD
},
48 { prefs::kOverscrollVerticalThresholdStart
,
49 OVERSCROLL_CONFIG_VERT_THRESHOLD_START
},
50 { prefs::kOverscrollHorizontalResistThreshold
,
51 OVERSCROLL_CONFIG_HORIZ_RESIST_AFTER
},
52 { prefs::kOverscrollVerticalResistThreshold
,
53 OVERSCROLL_CONFIG_VERT_RESIST_AFTER
},
55 overscroll_prefs
.assign(kOverscrollPrefs
,
56 kOverscrollPrefs
+ arraysize(kOverscrollPrefs
));
58 return overscroll_prefs
;
61 // This class manages gesture configuration preferences.
62 class GesturePrefsObserver
: public KeyedService
{
64 explicit GesturePrefsObserver(PrefService
* prefs
);
65 virtual ~GesturePrefsObserver();
67 // KeyedService implementation.
68 virtual void Shutdown() OVERRIDE
;
71 // Notification callback invoked when browser-side preferences
72 // are updated and need to be pushed into ui::GesturePreferences.
75 // Notification callback invoked when the fling deacceleration
76 // gesture preferences are changed from chrome://gesture.
77 // Broadcasts the changes all renderers where they are used.
80 // Notification helper to push overscroll preferences into
82 void UpdateOverscrollPrefs();
84 PrefChangeRegistrar registrar_
;
87 DISALLOW_COPY_AND_ASSIGN(GesturePrefsObserver
);
90 // The list of prefs we want to observe.
91 // Note that this collection of settings should correspond to the settings used
92 // in ui/events/gestures/gesture_configuration.h
93 const char* kPrefsToObserve
[] = {
94 prefs::kFlingAccelerationCurveCoefficient0
,
95 prefs::kFlingAccelerationCurveCoefficient1
,
96 prefs::kFlingAccelerationCurveCoefficient2
,
97 prefs::kFlingAccelerationCurveCoefficient3
,
98 prefs::kFlingMaxCancelToDownTimeInMs
,
99 prefs::kFlingMaxTapGapTimeInMs
,
100 prefs::kTabScrubActivationDelayInMS
,
101 prefs::kMaxSeparationForGestureTouchesInPixels
,
102 prefs::kSemiLongPressTimeInSeconds
,
105 const char* kFlingTouchpadPrefs
[] = {
106 prefs::kFlingCurveTouchpadAlpha
,
107 prefs::kFlingCurveTouchpadBeta
,
108 prefs::kFlingCurveTouchpadGamma
111 const char* kFlingTouchscreenPrefs
[] = {
112 prefs::kFlingCurveTouchscreenAlpha
,
113 prefs::kFlingCurveTouchscreenBeta
,
114 prefs::kFlingCurveTouchscreenGamma
,
117 GesturePrefsObserver::GesturePrefsObserver(PrefService
* prefs
)
119 registrar_
.Init(prefs
);
120 registrar_
.RemoveAll();
121 base::Closure callback
= base::Bind(&GesturePrefsObserver::Update
,
122 base::Unretained(this));
124 base::Closure notify_callback
= base::Bind(&GesturePrefsObserver::Notify
,
125 base::Unretained(this));
127 for (size_t i
= 0; i
< arraysize(kPrefsToObserve
); ++i
)
128 registrar_
.Add(kPrefsToObserve
[i
], callback
);
130 const std::vector
<OverscrollPref
>& overscroll_prefs
= GetOverscrollPrefs();
131 for (size_t i
= 0; i
< overscroll_prefs
.size(); ++i
)
132 registrar_
.Add(overscroll_prefs
[i
].pref_name
, callback
);
134 for (size_t i
= 0; i
< arraysize(kFlingTouchpadPrefs
); ++i
)
135 registrar_
.Add(kFlingTouchpadPrefs
[i
], notify_callback
);
136 for (size_t i
= 0; i
< arraysize(kFlingTouchscreenPrefs
); ++i
)
137 registrar_
.Add(kFlingTouchscreenPrefs
[i
], notify_callback
);
142 GesturePrefsObserver::~GesturePrefsObserver() {}
144 void GesturePrefsObserver::Shutdown() {
145 registrar_
.RemoveAll();
148 void GesturePrefsObserver::Update() {
149 GestureConfiguration::set_fling_acceleration_curve_coefficients(0,
150 prefs_
->GetDouble(prefs::kFlingAccelerationCurveCoefficient0
));
151 GestureConfiguration::set_fling_acceleration_curve_coefficients(1,
152 prefs_
->GetDouble(prefs::kFlingAccelerationCurveCoefficient1
));
153 GestureConfiguration::set_fling_acceleration_curve_coefficients(2,
154 prefs_
->GetDouble(prefs::kFlingAccelerationCurveCoefficient2
));
155 GestureConfiguration::set_fling_acceleration_curve_coefficients(3,
156 prefs_
->GetDouble(prefs::kFlingAccelerationCurveCoefficient3
));
157 GestureConfiguration::set_fling_max_cancel_to_down_time_in_ms(
158 prefs_
->GetInteger(prefs::kFlingMaxCancelToDownTimeInMs
));
159 GestureConfiguration::set_fling_max_tap_gap_time_in_ms(
160 prefs_
->GetInteger(prefs::kFlingMaxTapGapTimeInMs
));
161 GestureConfiguration::set_tab_scrub_activation_delay_in_ms(
162 prefs_
->GetInteger(prefs::kTabScrubActivationDelayInMS
));
163 GestureConfiguration::set_semi_long_press_time_in_seconds(
165 prefs::kSemiLongPressTimeInSeconds
));
166 GestureConfiguration::set_max_separation_for_gesture_touches_in_pixels(
168 prefs::kMaxSeparationForGestureTouchesInPixels
));
170 UpdateOverscrollPrefs();
173 void GesturePrefsObserver::UpdateOverscrollPrefs() {
174 const std::vector
<OverscrollPref
>& overscroll_prefs
= GetOverscrollPrefs();
175 for (size_t i
= 0; i
< overscroll_prefs
.size(); ++i
) {
176 content::SetOverscrollConfig(overscroll_prefs
[i
].config
,
177 static_cast<float>(prefs_
->GetDouble(overscroll_prefs
[i
].pref_name
)));
181 void GesturePrefsObserver::Notify() {
182 // Must do a notify to distribute the changes to all renderers.
183 content::NotificationService
* service
=
184 content::NotificationService::current();
185 service
->Notify(chrome::NOTIFICATION_BROWSER_FLING_CURVE_PARAMETERS_CHANGED
,
186 content::Source
<GesturePrefsObserver
>(this),
187 content::NotificationService::NoDetails());
193 GesturePrefsObserverFactoryAura
*
194 GesturePrefsObserverFactoryAura::GetInstance() {
195 return Singleton
<GesturePrefsObserverFactoryAura
>::get();
198 GesturePrefsObserverFactoryAura::GesturePrefsObserverFactoryAura()
199 : BrowserContextKeyedServiceFactory(
200 "GesturePrefsObserverAura",
201 BrowserContextDependencyManager::GetInstance()) {}
203 GesturePrefsObserverFactoryAura::~GesturePrefsObserverFactoryAura() {}
205 KeyedService
* GesturePrefsObserverFactoryAura::BuildServiceInstanceFor(
206 content::BrowserContext
* profile
) const {
207 return new GesturePrefsObserver(static_cast<Profile
*>(profile
)->GetPrefs());
210 void GesturePrefsObserverFactoryAura::RegisterOverscrollPrefs(
211 user_prefs::PrefRegistrySyncable
* registry
) {
212 const std::vector
<OverscrollPref
>& overscroll_prefs
= GetOverscrollPrefs();
214 for (size_t i
= 0; i
< overscroll_prefs
.size(); ++i
) {
215 registry
->RegisterDoublePref(
216 overscroll_prefs
[i
].pref_name
,
217 content::GetOverscrollConfig(overscroll_prefs
[i
].config
),
218 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
222 void GesturePrefsObserverFactoryAura::RegisterFlingCurveParameters(
223 user_prefs::PrefRegistrySyncable
* registry
) {
224 content::RendererPreferences def_prefs
;
226 for (size_t i
= 0; i
< arraysize(kFlingTouchpadPrefs
); i
++)
227 registry
->RegisterDoublePref(
228 kFlingTouchpadPrefs
[i
],
229 def_prefs
.touchpad_fling_profile
[i
],
230 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
232 for (size_t i
= 0; i
< arraysize(kFlingTouchscreenPrefs
); i
++)
233 registry
->RegisterDoublePref(
234 kFlingTouchscreenPrefs
[i
],
235 def_prefs
.touchscreen_fling_profile
[i
],
236 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
239 void GesturePrefsObserverFactoryAura::RegisterProfilePrefs(
240 user_prefs::PrefRegistrySyncable
* registry
) {
241 registry
->RegisterDoublePref(
242 prefs::kFlingAccelerationCurveCoefficient0
,
243 GestureConfiguration::fling_acceleration_curve_coefficients(0),
244 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
245 registry
->RegisterDoublePref(
246 prefs::kFlingAccelerationCurveCoefficient1
,
247 GestureConfiguration::fling_acceleration_curve_coefficients(1),
248 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
249 registry
->RegisterDoublePref(
250 prefs::kFlingAccelerationCurveCoefficient2
,
251 GestureConfiguration::fling_acceleration_curve_coefficients(2),
252 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
253 registry
->RegisterDoublePref(
254 prefs::kFlingAccelerationCurveCoefficient3
,
255 GestureConfiguration::fling_acceleration_curve_coefficients(3),
256 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
257 registry
->RegisterIntegerPref(
258 prefs::kFlingMaxCancelToDownTimeInMs
,
259 GestureConfiguration::fling_max_cancel_to_down_time_in_ms(),
260 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
261 registry
->RegisterIntegerPref(
262 prefs::kFlingMaxTapGapTimeInMs
,
263 GestureConfiguration::fling_max_tap_gap_time_in_ms(),
264 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
265 registry
->RegisterIntegerPref(
266 prefs::kTabScrubActivationDelayInMS
,
267 GestureConfiguration::tab_scrub_activation_delay_in_ms(),
268 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
269 registry
->RegisterDoublePref(
270 prefs::kSemiLongPressTimeInSeconds
,
271 GestureConfiguration::semi_long_press_time_in_seconds(),
272 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
273 registry
->RegisterDoublePref(
274 prefs::kMaxSeparationForGestureTouchesInPixels
,
275 GestureConfiguration::max_separation_for_gesture_touches_in_pixels(),
276 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
277 RegisterOverscrollPrefs(registry
);
278 RegisterFlingCurveParameters(registry
);
282 GesturePrefsObserverFactoryAura::ServiceIsCreatedWithBrowserContext() const {
283 // Create the observer as soon as the profile is created.
287 content::BrowserContext
*
288 GesturePrefsObserverFactoryAura::GetBrowserContextToUse(
289 content::BrowserContext
* context
) const {
290 // Use same gesture preferences on incognito windows.
291 return chrome::GetBrowserContextRedirectedInIncognito(context
);
294 bool GesturePrefsObserverFactoryAura::ServiceIsNULLWhileTesting() const {
295 // Some tests replace the PrefService of the TestingProfile after the
296 // GesturePrefsObserver has been created, which makes Shutdown()
297 // remove the registrar from a non-existent PrefService.