1// Copyright 2014 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
5package org.chromium.chrome.browser.accessibility;
6
7import android.content.Context;
8import android.content.SharedPreferences;
9import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
10import android.preference.PreferenceManager;
11
12import org.chromium.base.CalledByNative;
13import org.chromium.base.NativeCall;
14import org.chromium.base.ThreadUtils;
15
16import java.util.HashMap;
17import java.util.Map;
18
19/**
20 * Singleton wrapper class for native FontSizePrefs. Provides support for preferences for Font
21 * Scale Factor, Force Enable Zoom, and User Set Force Enable Zoom. User Set Force Enable Zoom
22 * tracks whether the user  has manually set the force enable zoom button, while Force Enable Zoom
23 * tracks whether force enable zoom is on or off. Font Scale Factor reflects the global font scale.
24 */
25public class FontSizePrefs implements OnSharedPreferenceChangeListener {
26    public static final String PREF_FORCE_ENABLE_ZOOM = "force_enable_zoom";
27    public static final String PREF_TEXT_SCALE = "text_scale";
28    public static final String PREF_USER_SET_FORCE_ENABLE_ZOOM = "user_set_force_enable_zoom";
29
30    private static FontSizePrefs sFontSizePrefs;
31    private final long mFontSizePrefsAndroidPtr;
32    private final SharedPreferences mSharedPreferences;
33    private final Map<Observer, FontSizePrefsObserverWrapper> mObserverMap;
34
35    /**
36     * Observer interface for observing changes in FontScaleFactor, ForceEnableZoom and
37     * UserSetForceEnableZoom.
38     */
39    public interface Observer {
40        void onChangeFontSize(float newFontSize);
41        void onChangeForceEnableZoom(boolean enabled);
42        void onChangeUserSetForceEnableZoom(boolean enabled);
43    }
44
45    /**
46     * Wrapper for FontSizePrefsObserverAndroid.
47     */
48    private static class FontSizePrefsObserverWrapper {
49        private final Observer mFontSizePrefsObserver;
50        private final long mNativeFontSizePrefsObserverWrapperPtr;
51
52        public FontSizePrefsObserverWrapper(Observer observer) {
53            mNativeFontSizePrefsObserverWrapperPtr = nativeInitObserverAndroid();
54            mFontSizePrefsObserver = observer;
55        }
56
57        public long getNativePtr() {
58            return mNativeFontSizePrefsObserverWrapperPtr;
59        }
60
61        public void destroy() {
62            nativeDestroyObserverAndroid(mNativeFontSizePrefsObserverWrapperPtr);
63        }
64
65        @CalledByNative("FontSizePrefsObserverWrapper")
66        public void onChangeFontSize(float newFontSize) {
67            mFontSizePrefsObserver.onChangeFontSize(newFontSize);
68        }
69
70        @CalledByNative("FontSizePrefsObserverWrapper")
71        public void onChangeForceEnableZoom(boolean enabled) {
72            mFontSizePrefsObserver.onChangeForceEnableZoom(enabled);
73        }
74
75        public void onChangeUserSetForceEnableZoom(boolean enabled) {
76            mFontSizePrefsObserver.onChangeUserSetForceEnableZoom(enabled);
77        }
78
79        @NativeCall("FontSizePrefsObserverWrapper")
80        private native long nativeInitObserverAndroid();
81
82        @NativeCall("FontSizePrefsObserverWrapper")
83        private native void nativeDestroyObserverAndroid(long nativeFontSizePrefsObserverAndroid);
84    }
85
86    private FontSizePrefs(Context context) {
87        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
88        mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
89        mFontSizePrefsAndroidPtr = nativeInit();
90        mObserverMap = new HashMap<Observer, FontSizePrefsObserverWrapper>();
91    }
92
93    /**
94     * Returns the FontSizePrefs corresponding to the inputted Profile. If no FontSizePrefs existed,
95     * this method will create one.
96     */
97    public static FontSizePrefs getInstance(Context context) {
98        ThreadUtils.assertOnUiThread();
99        if (sFontSizePrefs == null) {
100            sFontSizePrefs = new FontSizePrefs(context);
101        }
102        return sFontSizePrefs;
103    }
104
105    /**
106     * Adds the observer to listen for Font Scale and Force Enable Zoom preferences.
107     * @return true if the observerMap was changed as a result of the call.
108     */
109    public boolean addObserver(Observer obs) {
110        if (mObserverMap.containsKey(obs)) return false;
111        FontSizePrefsObserverWrapper wrappedObserver =
112                new FontSizePrefsObserverWrapper(obs);
113        nativeAddObserver(mFontSizePrefsAndroidPtr, wrappedObserver.getNativePtr());
114        mObserverMap.put(obs, wrappedObserver);
115        return true;
116    }
117
118    /**
119     * Removes the observer and unregisters it from Font Scale and Force Enable Zoom changes.
120     * @return true if an observer was removed as a result of the call.
121     */
122    public boolean removeObserver(Observer obs) {
123        FontSizePrefsObserverWrapper wrappedObserver = mObserverMap.remove(obs);
124        if (wrappedObserver == null) return false;
125        nativeRemoveObserver(mFontSizePrefsAndroidPtr, wrappedObserver.getNativePtr());
126        wrappedObserver.destroy();
127        return true;
128    }
129
130    /**
131     * Sets UserSetForceEnableZoom. This is the only one of three preferences stored through
132     * SharedPreferences.
133     */
134    public void setUserSetForceEnableZoom(boolean enabled) {
135        SharedPreferences.Editor sharedPreferencesEditor = mSharedPreferences.edit();
136        sharedPreferencesEditor.putBoolean(PREF_USER_SET_FORCE_ENABLE_ZOOM, enabled);
137        sharedPreferencesEditor.apply();
138    }
139
140    /**
141     * Returns true if user has manually set ForceEnableZoom and false otherwise.
142     */
143    public boolean getUserSetForceEnableZoom() {
144        return mSharedPreferences.getBoolean(PREF_USER_SET_FORCE_ENABLE_ZOOM,
145                false);
146    }
147
148    public void setFontScaleFactor(float fontScaleFactor) {
149        nativeSetFontScaleFactor(mFontSizePrefsAndroidPtr, fontScaleFactor);
150    }
151
152    @Override
153    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
154        if (PREF_USER_SET_FORCE_ENABLE_ZOOM.equals(key)) {
155            for (FontSizePrefsObserverWrapper obsWrapper : mObserverMap.values()) {
156                obsWrapper.onChangeUserSetForceEnableZoom(getUserSetForceEnableZoom());
157            }
158        }
159    }
160
161    public float getFontScaleFactor() {
162        return nativeGetFontScaleFactor(mFontSizePrefsAndroidPtr);
163    }
164
165    public void setForceEnableZoom(boolean enabled) {
166        nativeSetForceEnableZoom(mFontSizePrefsAndroidPtr, enabled);
167    }
168
169    public boolean getForceEnableZoom() {
170        return nativeGetForceEnableZoom(mFontSizePrefsAndroidPtr);
171    }
172
173    private native void nativeAddObserver(long nativeFontSizePrefsAndroid,
174            long nativeObserverPtr);
175
176    private native void nativeRemoveObserver(long nativeFontSizePrefsAndroid,
177            long nativeObserverPtr);
178
179    private native long nativeInit();
180
181    private native void nativeSetFontScaleFactor(long nativeFontSizePrefsAndroid, float font);
182
183    private native float nativeGetFontScaleFactor(long nativeFontSizePrefsAndroid);
184
185    private native boolean nativeGetForceEnableZoom(long nativeFontSizePrefsAndroid);
186
187    private native void nativeSetForceEnableZoom(long nativeFontSizePrefsAndroid, boolean enabled);
188}
189