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/browser_context_keyed_service/browser_context_dependency_manager.h"
19 #include "components/user_prefs/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 // TODO(rjkroege): Remove this deprecated pref in M29. http://crbug.com/160243.
31 const char kTouchScreenFlingAccelerationAdjustment[] =
32 "gesture.touchscreen_fling_acceleration_adjustment";
34 struct OverscrollPref {
35 const char* pref_name;
36 content::OverscrollConfig config;
39 const std::vector<OverscrollPref>& GetOverscrollPrefs() {
40 CR_DEFINE_STATIC_LOCAL(std::vector<OverscrollPref>, overscroll_prefs, ());
41 if (overscroll_prefs.empty()) {
42 using namespace content;
43 const OverscrollPref kOverscrollPrefs[] = {
44 { prefs::kOverscrollHorizontalThresholdComplete,
45 OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE },
46 { prefs::kOverscrollVerticalThresholdComplete,
47 OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE },
48 { prefs::kOverscrollMinimumThresholdStart,
49 OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN },
50 { prefs::kOverscrollMinimumThresholdStartTouchpad,
51 OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD },
52 { prefs::kOverscrollVerticalThresholdStart,
53 OVERSCROLL_CONFIG_VERT_THRESHOLD_START },
54 { prefs::kOverscrollHorizontalResistThreshold,
55 OVERSCROLL_CONFIG_HORIZ_RESIST_AFTER },
56 { prefs::kOverscrollVerticalResistThreshold,
57 OVERSCROLL_CONFIG_VERT_RESIST_AFTER },
59 overscroll_prefs.assign(kOverscrollPrefs,
60 kOverscrollPrefs + arraysize(kOverscrollPrefs));
62 return overscroll_prefs;
65 // This class manages gesture configuration preferences.
66 class GesturePrefsObserver : public BrowserContextKeyedService {
68 explicit GesturePrefsObserver(PrefService* prefs);
69 virtual ~GesturePrefsObserver();
71 // BrowserContextKeyedService implementation.
72 virtual void Shutdown() OVERRIDE;
75 // Notification callback invoked when browser-side preferences
76 // are updated and need to be pushed into ui::GesturePreferences.
79 // Notification callback invoked when the fling deacceleration
80 // gesture preferences are changed from chrome://gesture.
81 // Broadcasts the changes all renderers where they are used.
84 // Notification helper to push overscroll preferences into
86 void UpdateOverscrollPrefs();
88 PrefChangeRegistrar registrar_;
91 DISALLOW_COPY_AND_ASSIGN(GesturePrefsObserver);
94 // The list of prefs we want to observe.
95 // Note that this collection of settings should correspond to the settings used
96 // in ui/events/gestures/gesture_configuration.h
97 const char* kPrefsToObserve[] = {
98 prefs::kFlingAccelerationCurveCoefficient0,
99 prefs::kFlingAccelerationCurveCoefficient1,
100 prefs::kFlingAccelerationCurveCoefficient2,
101 prefs::kFlingAccelerationCurveCoefficient3,
102 prefs::kFlingMaxCancelToDownTimeInMs,
103 prefs::kFlingMaxTapGapTimeInMs,
104 prefs::kTabScrubActivationDelayInMS,
105 prefs::kFlingVelocityCap,
106 prefs::kLongPressTimeInSeconds,
107 prefs::kMaxDistanceForTwoFingerTapInPixels,
108 prefs::kMaxSecondsBetweenDoubleClick,
109 prefs::kMaxSeparationForGestureTouchesInPixels,
110 prefs::kMaxSwipeDeviationRatio,
111 prefs::kMaxTouchDownDurationInSecondsForClick,
112 prefs::kMaxTouchMoveInPixelsForClick,
113 prefs::kMinDistanceForPinchScrollInPixels,
114 prefs::kMinFlickSpeedSquared,
115 prefs::kMinPinchUpdateDistanceInPixels,
116 prefs::kMinRailBreakVelocity,
117 prefs::kMinScrollDeltaSquared,
118 prefs::kMinScrollSuccessiveVelocityEvents,
119 prefs::kMinSwipeSpeed,
120 prefs::kMinTouchDownDurationInSecondsForClick,
121 prefs::kPointsBufferedForVelocity,
122 prefs::kRailBreakProportion,
123 prefs::kRailStartProportion,
124 prefs::kSemiLongPressTimeInSeconds,
127 const char* kFlingTouchpadPrefs[] = {
128 prefs::kFlingCurveTouchpadAlpha,
129 prefs::kFlingCurveTouchpadBeta,
130 prefs::kFlingCurveTouchpadGamma
133 const char* kFlingTouchscreenPrefs[] = {
134 prefs::kFlingCurveTouchscreenAlpha,
135 prefs::kFlingCurveTouchscreenBeta,
136 prefs::kFlingCurveTouchscreenGamma,
139 GesturePrefsObserver::GesturePrefsObserver(PrefService* prefs)
141 // Clear for migration.
142 prefs->ClearPref(kTouchScreenFlingAccelerationAdjustment);
144 // TODO(mohsen): Remove following code in M32. By then, gesture prefs will
145 // have been cleared for majority of the users: crbug.com/269292.
146 // Do a one-time wipe of all gesture preferences.
147 if (!prefs->GetBoolean(prefs::kGestureConfigIsTrustworthy)) {
148 for (size_t i = 0; i < arraysize(kPrefsToObserve); ++i)
149 prefs->ClearPref(kPrefsToObserve[i]);
151 const std::vector<OverscrollPref>& overscroll_prefs = GetOverscrollPrefs();
152 for (size_t i = 0; i < overscroll_prefs.size(); ++i)
153 prefs->ClearPref(overscroll_prefs[i].pref_name);
155 for (size_t i = 0; i < arraysize(kFlingTouchpadPrefs); ++i)
156 prefs->ClearPref(kFlingTouchpadPrefs[i]);
158 for (size_t i = 0; i < arraysize(kFlingTouchscreenPrefs); ++i)
159 prefs->ClearPref(kFlingTouchscreenPrefs[i]);
161 prefs->SetBoolean(prefs::kGestureConfigIsTrustworthy, true);
164 registrar_.Init(prefs);
165 registrar_.RemoveAll();
166 base::Closure callback = base::Bind(&GesturePrefsObserver::Update,
167 base::Unretained(this));
169 base::Closure notify_callback = base::Bind(&GesturePrefsObserver::Notify,
170 base::Unretained(this));
172 for (size_t i = 0; i < arraysize(kPrefsToObserve); ++i)
173 registrar_.Add(kPrefsToObserve[i], callback);
175 const std::vector<OverscrollPref>& overscroll_prefs = GetOverscrollPrefs();
176 for (size_t i = 0; i < overscroll_prefs.size(); ++i)
177 registrar_.Add(overscroll_prefs[i].pref_name, callback);
179 for (size_t i = 0; i < arraysize(kFlingTouchpadPrefs); ++i)
180 registrar_.Add(kFlingTouchpadPrefs[i], notify_callback);
181 for (size_t i = 0; i < arraysize(kFlingTouchscreenPrefs); ++i)
182 registrar_.Add(kFlingTouchscreenPrefs[i], notify_callback);
187 GesturePrefsObserver::~GesturePrefsObserver() {}
189 void GesturePrefsObserver::Shutdown() {
190 registrar_.RemoveAll();
193 void GesturePrefsObserver::Update() {
194 GestureConfiguration::set_fling_acceleration_curve_coefficients(0,
195 prefs_->GetDouble(prefs::kFlingAccelerationCurveCoefficient0));
196 GestureConfiguration::set_fling_acceleration_curve_coefficients(1,
197 prefs_->GetDouble(prefs::kFlingAccelerationCurveCoefficient1));
198 GestureConfiguration::set_fling_acceleration_curve_coefficients(2,
199 prefs_->GetDouble(prefs::kFlingAccelerationCurveCoefficient2));
200 GestureConfiguration::set_fling_acceleration_curve_coefficients(3,
201 prefs_->GetDouble(prefs::kFlingAccelerationCurveCoefficient3));
202 GestureConfiguration::set_fling_max_cancel_to_down_time_in_ms(
203 prefs_->GetInteger(prefs::kFlingMaxCancelToDownTimeInMs));
204 GestureConfiguration::set_fling_max_tap_gap_time_in_ms(
205 prefs_->GetInteger(prefs::kFlingMaxTapGapTimeInMs));
206 GestureConfiguration::set_tab_scrub_activation_delay_in_ms(
207 prefs_->GetInteger(prefs::kTabScrubActivationDelayInMS));
208 GestureConfiguration::set_fling_velocity_cap(
209 prefs_->GetDouble(prefs::kFlingVelocityCap));
210 GestureConfiguration::set_long_press_time_in_seconds(
212 prefs::kLongPressTimeInSeconds));
213 GestureConfiguration::set_semi_long_press_time_in_seconds(
215 prefs::kSemiLongPressTimeInSeconds));
216 GestureConfiguration::set_max_distance_for_two_finger_tap_in_pixels(
218 prefs::kMaxDistanceForTwoFingerTapInPixels));
219 GestureConfiguration::set_max_seconds_between_double_click(
221 prefs::kMaxSecondsBetweenDoubleClick));
222 GestureConfiguration::set_max_separation_for_gesture_touches_in_pixels(
224 prefs::kMaxSeparationForGestureTouchesInPixels));
225 GestureConfiguration::set_max_swipe_deviation_ratio(
227 prefs::kMaxSwipeDeviationRatio));
228 GestureConfiguration::set_max_touch_down_duration_in_seconds_for_click(
230 prefs::kMaxTouchDownDurationInSecondsForClick));
231 GestureConfiguration::set_max_touch_move_in_pixels_for_click(
233 prefs::kMaxTouchMoveInPixelsForClick));
234 GestureConfiguration::set_max_distance_between_taps_for_double_tap(
236 prefs::kMaxDistanceBetweenTapsForDoubleTap));
237 GestureConfiguration::set_min_distance_for_pinch_scroll_in_pixels(
239 prefs::kMinDistanceForPinchScrollInPixels));
240 GestureConfiguration::set_min_flick_speed_squared(
242 prefs::kMinFlickSpeedSquared));
243 GestureConfiguration::set_min_pinch_update_distance_in_pixels(
245 prefs::kMinPinchUpdateDistanceInPixels));
246 GestureConfiguration::set_min_rail_break_velocity(
248 prefs::kMinRailBreakVelocity));
249 GestureConfiguration::set_min_scroll_delta_squared(
251 prefs::kMinScrollDeltaSquared));
252 GestureConfiguration::set_min_scroll_successive_velocity_events(
254 prefs::kMinScrollSuccessiveVelocityEvents));
255 GestureConfiguration::set_min_swipe_speed(
257 prefs::kMinSwipeSpeed));
258 GestureConfiguration::set_min_touch_down_duration_in_seconds_for_click(
260 prefs::kMinTouchDownDurationInSecondsForClick));
261 GestureConfiguration::set_points_buffered_for_velocity(
263 prefs::kPointsBufferedForVelocity));
264 GestureConfiguration::set_rail_break_proportion(
266 prefs::kRailBreakProportion));
267 GestureConfiguration::set_rail_start_proportion(
269 prefs::kRailStartProportion));
270 GestureConfiguration::set_scroll_prediction_seconds(
271 prefs_->GetDouble(prefs::kScrollPredictionSeconds));
272 GestureConfiguration::set_show_press_delay_in_ms(
273 prefs_->GetInteger(prefs::kShowPressDelayInMS));
275 UpdateOverscrollPrefs();
278 void GesturePrefsObserver::UpdateOverscrollPrefs() {
279 const std::vector<OverscrollPref>& overscroll_prefs = GetOverscrollPrefs();
280 for (size_t i = 0; i < overscroll_prefs.size(); ++i) {
281 content::SetOverscrollConfig(overscroll_prefs[i].config,
282 static_cast<float>(prefs_->GetDouble(overscroll_prefs[i].pref_name)));
286 void GesturePrefsObserver::Notify() {
287 // Must do a notify to distribute the changes to all renderers.
288 content::NotificationService* service =
289 content::NotificationService::current();
290 service->Notify(chrome::NOTIFICATION_BROWSER_FLING_CURVE_PARAMETERS_CHANGED,
291 content::Source<GesturePrefsObserver>(this),
292 content::NotificationService::NoDetails());
298 GesturePrefsObserverFactoryAura*
299 GesturePrefsObserverFactoryAura::GetInstance() {
300 return Singleton<GesturePrefsObserverFactoryAura>::get();
303 GesturePrefsObserverFactoryAura::GesturePrefsObserverFactoryAura()
304 : BrowserContextKeyedServiceFactory(
305 "GesturePrefsObserverAura",
306 BrowserContextDependencyManager::GetInstance()) {}
308 GesturePrefsObserverFactoryAura::~GesturePrefsObserverFactoryAura() {}
310 BrowserContextKeyedService*
311 GesturePrefsObserverFactoryAura::BuildServiceInstanceFor(
312 content::BrowserContext* profile) const {
313 return new GesturePrefsObserver(static_cast<Profile*>(profile)->GetPrefs());
316 void GesturePrefsObserverFactoryAura::RegisterOverscrollPrefs(
317 user_prefs::PrefRegistrySyncable* registry) {
318 const std::vector<OverscrollPref>& overscroll_prefs = GetOverscrollPrefs();
320 for (size_t i = 0; i < overscroll_prefs.size(); ++i) {
321 registry->RegisterDoublePref(
322 overscroll_prefs[i].pref_name,
323 content::GetOverscrollConfig(overscroll_prefs[i].config),
324 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
328 void GesturePrefsObserverFactoryAura::RegisterFlingCurveParameters(
329 user_prefs::PrefRegistrySyncable* registry) {
330 content::RendererPreferences def_prefs;
332 for (size_t i = 0; i < arraysize(kFlingTouchpadPrefs); i++)
333 registry->RegisterDoublePref(
334 kFlingTouchpadPrefs[i],
335 def_prefs.touchpad_fling_profile[i],
336 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
338 for (size_t i = 0; i < arraysize(kFlingTouchscreenPrefs); i++)
339 registry->RegisterDoublePref(
340 kFlingTouchscreenPrefs[i],
341 def_prefs.touchscreen_fling_profile[i],
342 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
345 void GesturePrefsObserverFactoryAura::RegisterProfilePrefs(
346 user_prefs::PrefRegistrySyncable* registry) {
347 registry->RegisterDoublePref(
348 prefs::kFlingAccelerationCurveCoefficient0,
349 GestureConfiguration::fling_acceleration_curve_coefficients(0),
350 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
351 registry->RegisterDoublePref(
352 prefs::kFlingAccelerationCurveCoefficient1,
353 GestureConfiguration::fling_acceleration_curve_coefficients(1),
354 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
355 registry->RegisterDoublePref(
356 prefs::kFlingAccelerationCurveCoefficient2,
357 GestureConfiguration::fling_acceleration_curve_coefficients(2),
358 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
359 registry->RegisterDoublePref(
360 prefs::kFlingAccelerationCurveCoefficient3,
361 GestureConfiguration::fling_acceleration_curve_coefficients(3),
362 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
363 registry->RegisterIntegerPref(
364 prefs::kFlingMaxCancelToDownTimeInMs,
365 GestureConfiguration::fling_max_cancel_to_down_time_in_ms(),
366 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
367 registry->RegisterIntegerPref(
368 prefs::kFlingMaxTapGapTimeInMs,
369 GestureConfiguration::fling_max_tap_gap_time_in_ms(),
370 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
371 registry->RegisterIntegerPref(
372 prefs::kTabScrubActivationDelayInMS,
373 GestureConfiguration::tab_scrub_activation_delay_in_ms(),
374 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
375 registry->RegisterDoublePref(
376 prefs::kFlingVelocityCap,
377 GestureConfiguration::fling_velocity_cap(),
378 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
379 registry->RegisterDoublePref(
380 prefs::kLongPressTimeInSeconds,
381 GestureConfiguration::long_press_time_in_seconds(),
382 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
383 registry->RegisterDoublePref(
384 prefs::kSemiLongPressTimeInSeconds,
385 GestureConfiguration::semi_long_press_time_in_seconds(),
386 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
387 registry->RegisterDoublePref(
388 prefs::kMaxDistanceForTwoFingerTapInPixels,
389 GestureConfiguration::max_distance_for_two_finger_tap_in_pixels(),
390 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
391 registry->RegisterDoublePref(
392 prefs::kMaxSecondsBetweenDoubleClick,
393 GestureConfiguration::max_seconds_between_double_click(),
394 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
395 registry->RegisterDoublePref(
396 prefs::kMaxSeparationForGestureTouchesInPixels,
397 GestureConfiguration::max_separation_for_gesture_touches_in_pixels(),
398 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
399 registry->RegisterDoublePref(
400 prefs::kMaxSwipeDeviationRatio,
401 GestureConfiguration::max_swipe_deviation_ratio(),
402 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
403 registry->RegisterDoublePref(
404 prefs::kMaxTouchDownDurationInSecondsForClick,
405 GestureConfiguration::max_touch_down_duration_in_seconds_for_click(),
406 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
407 registry->RegisterDoublePref(
408 prefs::kMaxTouchMoveInPixelsForClick,
409 GestureConfiguration::max_touch_move_in_pixels_for_click(),
410 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
411 registry->RegisterDoublePref(
412 prefs::kMaxDistanceBetweenTapsForDoubleTap,
413 GestureConfiguration::max_distance_between_taps_for_double_tap(),
414 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
415 registry->RegisterDoublePref(
416 prefs::kMinDistanceForPinchScrollInPixels,
417 GestureConfiguration::min_distance_for_pinch_scroll_in_pixels(),
418 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
419 registry->RegisterDoublePref(
420 prefs::kMinFlickSpeedSquared,
421 GestureConfiguration::min_flick_speed_squared(),
422 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
423 registry->RegisterDoublePref(
424 prefs::kMinPinchUpdateDistanceInPixels,
425 GestureConfiguration::min_pinch_update_distance_in_pixels(),
426 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
427 registry->RegisterDoublePref(
428 prefs::kMinRailBreakVelocity,
429 GestureConfiguration::min_rail_break_velocity(),
430 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
431 registry->RegisterDoublePref(
432 prefs::kMinScrollDeltaSquared,
433 GestureConfiguration::min_scroll_delta_squared(),
434 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
435 registry->RegisterIntegerPref(
436 prefs::kMinScrollSuccessiveVelocityEvents,
437 GestureConfiguration::min_scroll_successive_velocity_events(),
438 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
439 registry->RegisterDoublePref(
440 prefs::kMinSwipeSpeed,
441 GestureConfiguration::min_swipe_speed(),
442 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
443 registry->RegisterDoublePref(
444 prefs::kMinTouchDownDurationInSecondsForClick,
445 GestureConfiguration::min_touch_down_duration_in_seconds_for_click(),
446 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
447 registry->RegisterIntegerPref(
448 prefs::kPointsBufferedForVelocity,
449 GestureConfiguration::points_buffered_for_velocity(),
450 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
451 registry->RegisterDoublePref(
452 prefs::kRailBreakProportion,
453 GestureConfiguration::rail_break_proportion(),
454 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
455 registry->RegisterDoublePref(
456 prefs::kRailStartProportion,
457 GestureConfiguration::rail_start_proportion(),
458 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
459 registry->RegisterDoublePref(
460 prefs::kScrollPredictionSeconds,
461 GestureConfiguration::scroll_prediction_seconds(),
462 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
463 registry->RegisterIntegerPref(
464 prefs::kShowPressDelayInMS,
465 GestureConfiguration::show_press_delay_in_ms(),
466 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
468 // Register for migration.
469 registry->RegisterDoublePref(
470 kTouchScreenFlingAccelerationAdjustment,
472 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
474 RegisterOverscrollPrefs(registry);
475 RegisterFlingCurveParameters(registry);
477 // Register pref for a one-time wipe of all gesture preferences.
478 registry->RegisterBooleanPref(
479 prefs::kGestureConfigIsTrustworthy,
481 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
485 GesturePrefsObserverFactoryAura::ServiceIsCreatedWithBrowserContext() const {
486 // Create the observer as soon as the profile is created.
490 content::BrowserContext*
491 GesturePrefsObserverFactoryAura::GetBrowserContextToUse(
492 content::BrowserContext* context) const {
493 // Use same gesture preferences on incognito windows.
494 return chrome::GetBrowserContextRedirectedInIncognito(context);
497 bool GesturePrefsObserverFactoryAura::ServiceIsNULLWhileTesting() const {
498 // Some tests replace the PrefService of the TestingProfile after the
499 // GesturePrefsObserver has been created, which makes Shutdown()
500 // remove the registrar from a non-existent PrefService.