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/keyed_service/core/keyed_service.h"
20 #include "components/pref_registry/pref_registry_syncable.h"
21 #include "content/public/browser/notification_observer.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/overscroll_configuration.h"
24 #include "content/public/common/renderer_preferences.h"
25 #include "ui/events/gesture_detection/gesture_configuration.h"
27 using ui::GestureConfiguration
;
31 struct OverscrollPref
{
32 const char* pref_name
;
33 content::OverscrollConfig config
;
36 const std::vector
<OverscrollPref
>& GetOverscrollPrefs() {
37 CR_DEFINE_STATIC_LOCAL(std::vector
<OverscrollPref
>, overscroll_prefs
, ());
38 if (overscroll_prefs
.empty()) {
39 using namespace content
;
40 const OverscrollPref kOverscrollPrefs
[] = {
41 { prefs::kOverscrollHorizontalThresholdComplete
,
42 OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE
},
43 { prefs::kOverscrollVerticalThresholdComplete
,
44 OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE
},
45 { prefs::kOverscrollMinimumThresholdStart
,
46 OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN
},
47 { prefs::kOverscrollMinimumThresholdStartTouchpad
,
48 OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD
},
49 { prefs::kOverscrollVerticalThresholdStart
,
50 OVERSCROLL_CONFIG_VERT_THRESHOLD_START
},
51 { prefs::kOverscrollHorizontalResistThreshold
,
52 OVERSCROLL_CONFIG_HORIZ_RESIST_AFTER
},
53 { prefs::kOverscrollVerticalResistThreshold
,
54 OVERSCROLL_CONFIG_VERT_RESIST_AFTER
},
56 overscroll_prefs
.assign(kOverscrollPrefs
,
57 kOverscrollPrefs
+ arraysize(kOverscrollPrefs
));
59 return overscroll_prefs
;
62 // This class manages gesture configuration preferences.
63 class GesturePrefsObserver
: public KeyedService
{
65 explicit GesturePrefsObserver(PrefService
* prefs
);
66 ~GesturePrefsObserver() override
;
68 // KeyedService implementation.
69 void Shutdown() override
;
72 // Notification callback invoked when browser-side preferences
73 // are updated and need to be pushed into ui::GesturePreferences.
76 // Notification callback invoked when the fling deacceleration
77 // gesture preferences are changed from chrome://gesture.
78 // Broadcasts the changes all renderers where they are used.
81 // Notification helper to push overscroll preferences into
83 void UpdateOverscrollPrefs();
85 PrefChangeRegistrar registrar_
;
88 DISALLOW_COPY_AND_ASSIGN(GesturePrefsObserver
);
91 // The list of prefs we want to observe.
92 // Note that this collection of settings should correspond to the settings used
93 // in ui/events/gestures/gesture_configuration.h
94 const char* kPrefsToObserve
[] = {
95 prefs::kFlingMaxCancelToDownTimeInMs
,
96 prefs::kFlingMaxTapGapTimeInMs
,
97 prefs::kTabScrubActivationDelayInMs
,
98 prefs::kMaxSeparationForGestureTouchesInPixels
,
99 prefs::kSemiLongPressTimeInMs
,
102 const char* kPrefsToRemove
[] = {
103 "gesture.fling_acceleration_curve_coefficient_0",
104 "gesture.fling_acceleration_curve_coefficient_1",
105 "gesture.fling_acceleration_curve_coefficient_2",
106 "gesture.fling_acceleration_curve_coefficient_3",
107 "gesture.semi_long_press_time_in_seconds",
108 "flingcurve.touchpad_alpha",
109 "flingcurve.touchpad_beta",
110 "flingcurve.touchpad_gamma",
111 "flingcurve.touchscreen_alpha",
112 "flingcurve.touchscreen_beta",
113 "flingcurve.touchscreen_gamma",
116 GesturePrefsObserver::GesturePrefsObserver(PrefService
* prefs
)
118 for (size_t i
= 0; i
< arraysize(kPrefsToRemove
); ++i
) {
119 if (prefs
->FindPreference(kPrefsToRemove
[i
]))
120 prefs
->ClearPref(kPrefsToRemove
[i
]);
123 registrar_
.Init(prefs
);
124 registrar_
.RemoveAll();
125 base::Closure callback
= base::Bind(&GesturePrefsObserver::Update
,
126 base::Unretained(this));
128 base::Closure notify_callback
= base::Bind(&GesturePrefsObserver::Notify
,
129 base::Unretained(this));
131 for (size_t i
= 0; i
< arraysize(kPrefsToObserve
); ++i
)
132 registrar_
.Add(kPrefsToObserve
[i
], callback
);
134 const std::vector
<OverscrollPref
>& overscroll_prefs
= GetOverscrollPrefs();
135 for (size_t i
= 0; i
< overscroll_prefs
.size(); ++i
)
136 registrar_
.Add(overscroll_prefs
[i
].pref_name
, callback
);
141 GesturePrefsObserver::~GesturePrefsObserver() {}
143 void GesturePrefsObserver::Shutdown() {
144 registrar_
.RemoveAll();
147 void GesturePrefsObserver::Update() {
148 GestureConfiguration
* gesture_config
= GestureConfiguration::GetInstance();
149 gesture_config
->set_fling_max_cancel_to_down_time_in_ms(
150 prefs_
->GetInteger(prefs::kFlingMaxCancelToDownTimeInMs
));
151 gesture_config
->set_fling_max_tap_gap_time_in_ms(
152 prefs_
->GetInteger(prefs::kFlingMaxTapGapTimeInMs
));
153 gesture_config
->set_tab_scrub_activation_delay_in_ms(
154 prefs_
->GetInteger(prefs::kTabScrubActivationDelayInMs
));
155 gesture_config
->set_semi_long_press_time_in_ms(
156 prefs_
->GetInteger(prefs::kSemiLongPressTimeInMs
));
157 gesture_config
->set_max_separation_for_gesture_touches_in_pixels(
159 prefs_
->GetDouble(prefs::kMaxSeparationForGestureTouchesInPixels
)));
161 UpdateOverscrollPrefs();
164 void GesturePrefsObserver::UpdateOverscrollPrefs() {
165 const std::vector
<OverscrollPref
>& overscroll_prefs
= GetOverscrollPrefs();
166 for (size_t i
= 0; i
< overscroll_prefs
.size(); ++i
) {
167 content::SetOverscrollConfig(overscroll_prefs
[i
].config
,
168 static_cast<float>(prefs_
->GetDouble(overscroll_prefs
[i
].pref_name
)));
172 void GesturePrefsObserver::Notify() {
173 // Must do a notify to distribute the changes to all renderers.
174 content::NotificationService
* service
=
175 content::NotificationService::current();
176 service
->Notify(chrome::NOTIFICATION_BROWSER_FLING_CURVE_PARAMETERS_CHANGED
,
177 content::Source
<GesturePrefsObserver
>(this),
178 content::NotificationService::NoDetails());
184 GesturePrefsObserverFactoryAura
*
185 GesturePrefsObserverFactoryAura::GetInstance() {
186 return Singleton
<GesturePrefsObserverFactoryAura
>::get();
189 GesturePrefsObserverFactoryAura::GesturePrefsObserverFactoryAura()
190 : BrowserContextKeyedServiceFactory(
191 "GesturePrefsObserverAura",
192 BrowserContextDependencyManager::GetInstance()) {}
194 GesturePrefsObserverFactoryAura::~GesturePrefsObserverFactoryAura() {}
196 KeyedService
* GesturePrefsObserverFactoryAura::BuildServiceInstanceFor(
197 content::BrowserContext
* profile
) const {
198 return new GesturePrefsObserver(static_cast<Profile
*>(profile
)->GetPrefs());
201 void GesturePrefsObserverFactoryAura::RegisterOverscrollPrefs(
202 user_prefs::PrefRegistrySyncable
* registry
) {
203 const std::vector
<OverscrollPref
>& overscroll_prefs
= GetOverscrollPrefs();
205 for (size_t i
= 0; i
< overscroll_prefs
.size(); ++i
) {
206 registry
->RegisterDoublePref(
207 overscroll_prefs
[i
].pref_name
,
208 content::GetOverscrollConfig(overscroll_prefs
[i
].config
),
209 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
213 void GesturePrefsObserverFactoryAura::RegisterProfilePrefs(
214 user_prefs::PrefRegistrySyncable
* registry
) {
215 GestureConfiguration
* gesture_config
= GestureConfiguration::GetInstance();
216 registry
->RegisterIntegerPref(
217 prefs::kFlingMaxCancelToDownTimeInMs
,
218 gesture_config
->fling_max_cancel_to_down_time_in_ms(),
219 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
220 registry
->RegisterIntegerPref(
221 prefs::kFlingMaxTapGapTimeInMs
,
222 gesture_config
->fling_max_tap_gap_time_in_ms(),
223 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
224 registry
->RegisterIntegerPref(
225 prefs::kTabScrubActivationDelayInMs
,
226 gesture_config
->tab_scrub_activation_delay_in_ms(),
227 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
228 registry
->RegisterIntegerPref(
229 prefs::kSemiLongPressTimeInMs
,
230 gesture_config
->semi_long_press_time_in_ms(),
231 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
232 registry
->RegisterDoublePref(
233 prefs::kMaxSeparationForGestureTouchesInPixels
,
234 gesture_config
->max_separation_for_gesture_touches_in_pixels(),
235 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
236 RegisterOverscrollPrefs(registry
);
240 GesturePrefsObserverFactoryAura::ServiceIsCreatedWithBrowserContext() const {
241 // Create the observer as soon as the profile is created.
245 content::BrowserContext
*
246 GesturePrefsObserverFactoryAura::GetBrowserContextToUse(
247 content::BrowserContext
* context
) const {
248 // Use same gesture preferences on incognito windows.
249 return chrome::GetBrowserContextRedirectedInIncognito(context
);
252 bool GesturePrefsObserverFactoryAura::ServiceIsNULLWhileTesting() const {
253 // Some tests replace the PrefService of the TestingProfile after the
254 // GesturePrefsObserver has been created, which makes Shutdown()
255 // remove the registrar from a non-existent PrefService.