1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.browser;
18
19import android.app.ActivityManager;
20import android.content.ContentResolver;
21import android.content.Context;
22import android.content.SharedPreferences;
23import android.content.SharedPreferences.Editor;
24import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
25import android.net.ConnectivityManager;
26import android.net.NetworkInfo;
27import android.os.Build;
28import android.os.Message;
29import android.preference.PreferenceManager;
30import android.provider.Browser;
31import android.provider.Settings;
32import android.util.DisplayMetrics;
33import android.webkit.CookieManager;
34import android.webkit.GeolocationPermissions;
35import android.webkit.WebIconDatabase;
36import android.webkit.WebSettings;
37import android.webkit.WebSettings.LayoutAlgorithm;
38import android.webkit.WebSettings.PluginState;
39import android.webkit.WebSettings.TextSize;
40import android.webkit.WebSettings.ZoomDensity;
41import android.webkit.WebStorage;
42import android.webkit.WebView;
43import android.webkit.WebViewDatabase;
44
45import com.android.browser.homepages.HomeProvider;
46import com.android.browser.provider.BrowserProvider;
47import com.android.browser.search.SearchEngine;
48import com.android.browser.search.SearchEngines;
49
50import java.lang.ref.WeakReference;
51import java.util.Iterator;
52import java.util.LinkedList;
53import java.util.WeakHashMap;
54
55/**
56 * Class for managing settings
57 */
58public class BrowserSettings implements OnSharedPreferenceChangeListener,
59        PreferenceKeys {
60
61    // TODO: Do something with this UserAgent stuff
62    private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (X11; " +
63        "Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) " +
64        "Chrome/11.0.696.34 Safari/534.24";
65
66    private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " +
67        "CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 " +
68        "(KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7";
69
70    private static final String IPAD_USERAGENT = "Mozilla/5.0 (iPad; U; " +
71        "CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 " +
72        "(KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10";
73
74    private static final String FROYO_USERAGENT = "Mozilla/5.0 (Linux; U; " +
75        "Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 " +
76        "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
77
78    private static final String HONEYCOMB_USERAGENT = "Mozilla/5.0 (Linux; U; " +
79        "Android 3.1; en-us; Xoom Build/HMJ25) AppleWebKit/534.13 " +
80        "(KHTML, like Gecko) Version/4.0 Safari/534.13";
81
82    private static final String USER_AGENTS[] = { null,
83            DESKTOP_USERAGENT,
84            IPHONE_USERAGENT,
85            IPAD_USERAGENT,
86            FROYO_USERAGENT,
87            HONEYCOMB_USERAGENT,
88    };
89
90    // The minimum min font size
91    // Aka, the lower bounds for the min font size range
92    // which is 1:5..24
93    private static final int MIN_FONT_SIZE_OFFSET = 5;
94    // The initial value in the text zoom range
95    // This is what represents 100% in the SeekBarPreference range
96    private static final int TEXT_ZOOM_START_VAL = 10;
97    // The size of a single step in the text zoom range, in percent
98    private static final int TEXT_ZOOM_STEP = 5;
99    // The initial value in the double tap zoom range
100    // This is what represents 100% in the SeekBarPreference range
101    private static final int DOUBLE_TAP_ZOOM_START_VAL = 5;
102    // The size of a single step in the double tap zoom range, in percent
103    private static final int DOUBLE_TAP_ZOOM_STEP = 5;
104
105    private static BrowserSettings sInstance;
106
107    private Context mContext;
108    private SharedPreferences mPrefs;
109    private LinkedList<WeakReference<WebSettings>> mManagedSettings;
110    private Controller mController;
111    private WebStorageSizeManager mWebStorageSizeManager;
112    private WeakHashMap<WebSettings, String> mCustomUserAgents;
113    private static boolean sInitialized = false;
114    private boolean mNeedsSharedSync = true;
115    private float mFontSizeMult = 1.0f;
116
117    // Current state of network-dependent settings
118    private boolean mLinkPrefetchAllowed = true;
119
120    // Cached values
121    private int mPageCacheCapacity = 1;
122    private String mAppCachePath;
123
124    // Cached settings
125    private SearchEngine mSearchEngine;
126
127    private static String sFactoryResetUrl;
128
129    public static void initialize(final Context context) {
130        sInstance = new BrowserSettings(context);
131    }
132
133    public static BrowserSettings getInstance() {
134        return sInstance;
135    }
136
137    private BrowserSettings(Context context) {
138        mContext = context.getApplicationContext();
139        mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
140        mManagedSettings = new LinkedList<WeakReference<WebSettings>>();
141        mCustomUserAgents = new WeakHashMap<WebSettings, String>();
142        BackgroundHandler.execute(mSetup);
143    }
144
145    public void setController(Controller controller) {
146        mController = controller;
147        if (sInitialized) {
148            syncSharedSettings();
149        }
150    }
151
152    public void startManagingSettings(WebSettings settings) {
153
154        if (mNeedsSharedSync) {
155            syncSharedSettings();
156        }
157
158        synchronized (mManagedSettings) {
159            syncStaticSettings(settings);
160            syncSetting(settings);
161            mManagedSettings.add(new WeakReference<WebSettings>(settings));
162        }
163    }
164
165    public void stopManagingSettings(WebSettings settings) {
166        Iterator<WeakReference<WebSettings>> iter = mManagedSettings.iterator();
167        while (iter.hasNext()) {
168            WeakReference<WebSettings> ref = iter.next();
169            if (ref.get() == settings) {
170                iter.remove();
171                return;
172            }
173        }
174    }
175
176    private Runnable mSetup = new Runnable() {
177
178        @Override
179        public void run() {
180            DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
181            mFontSizeMult = metrics.scaledDensity / metrics.density;
182            // the cost of one cached page is ~3M (measured using nytimes.com). For
183            // low end devices, we only cache one page. For high end devices, we try
184            // to cache more pages, currently choose 5.
185            if (ActivityManager.staticGetMemoryClass() > 16) {
186                mPageCacheCapacity = 5;
187            }
188            mWebStorageSizeManager = new WebStorageSizeManager(mContext,
189                    new WebStorageSizeManager.StatFsDiskInfo(getAppCachePath()),
190                    new WebStorageSizeManager.WebKitAppCacheInfo(getAppCachePath()));
191            // Workaround b/5254577
192            mPrefs.registerOnSharedPreferenceChangeListener(BrowserSettings.this);
193            if (Build.VERSION.CODENAME.equals("REL")) {
194                // This is a release build, always startup with debug disabled
195                setDebugEnabled(false);
196            }
197            if (mPrefs.contains(PREF_TEXT_SIZE)) {
198                /*
199                 * Update from TextSize enum to zoom percent
200                 * SMALLEST is 50%
201                 * SMALLER is 75%
202                 * NORMAL is 100%
203                 * LARGER is 150%
204                 * LARGEST is 200%
205                 */
206                switch (getTextSize()) {
207                case SMALLEST:
208                    setTextZoom(50);
209                    break;
210                case SMALLER:
211                    setTextZoom(75);
212                    break;
213                case LARGER:
214                    setTextZoom(150);
215                    break;
216                case LARGEST:
217                    setTextZoom(200);
218                    break;
219                }
220                mPrefs.edit().remove(PREF_TEXT_SIZE).apply();
221            }
222
223            sFactoryResetUrl = mContext.getResources().getString(R.string.homepage_base);
224            if (sFactoryResetUrl.indexOf("{CID}") != -1) {
225                sFactoryResetUrl = sFactoryResetUrl.replace("{CID}",
226                    BrowserProvider.getClientId(mContext.getContentResolver()));
227            }
228
229            synchronized (BrowserSettings.class) {
230                sInitialized = true;
231                BrowserSettings.class.notifyAll();
232            }
233        }
234    };
235
236    private static void requireInitialization() {
237        synchronized (BrowserSettings.class) {
238            while (!sInitialized) {
239                try {
240                    BrowserSettings.class.wait();
241                } catch (InterruptedException e) {
242                }
243            }
244        }
245    }
246
247    /**
248     * Syncs all the settings that have a Preference UI
249     */
250    private void syncSetting(WebSettings settings) {
251        settings.setGeolocationEnabled(enableGeolocation());
252        settings.setJavaScriptEnabled(enableJavascript());
253        settings.setLightTouchEnabled(enableLightTouch());
254        settings.setNavDump(enableNavDump());
255        settings.setDefaultTextEncodingName(getDefaultTextEncoding());
256        settings.setDefaultZoom(getDefaultZoom());
257        settings.setMinimumFontSize(getMinimumFontSize());
258        settings.setMinimumLogicalFontSize(getMinimumFontSize());
259        settings.setPluginState(getPluginState());
260        settings.setTextZoom(getTextZoom());
261        settings.setLayoutAlgorithm(getLayoutAlgorithm());
262        settings.setJavaScriptCanOpenWindowsAutomatically(!blockPopupWindows());
263        settings.setLoadsImagesAutomatically(loadImages());
264        settings.setLoadWithOverviewMode(loadPageInOverviewMode());
265        settings.setSavePassword(rememberPasswords());
266        settings.setSaveFormData(saveFormdata());
267        settings.setUseWideViewPort(isWideViewport());
268
269        String ua = mCustomUserAgents.get(settings);
270        if (ua != null) {
271            settings.setUserAgentString(ua);
272        } else {
273            settings.setUserAgentString(USER_AGENTS[getUserAgent()]);
274        }
275    }
276
277    /**
278     * Syncs all the settings that have no UI
279     * These cannot change, so we only need to set them once per WebSettings
280     */
281    private void syncStaticSettings(WebSettings settings) {
282        settings.setDefaultFontSize(16);
283        settings.setDefaultFixedFontSize(13);
284
285        // WebView inside Browser doesn't want initial focus to be set.
286        settings.setNeedInitialFocus(false);
287        // Browser supports multiple windows
288        settings.setSupportMultipleWindows(true);
289        // enable smooth transition for better performance during panning or
290        // zooming
291        settings.setEnableSmoothTransition(true);
292        // disable content url access
293        settings.setAllowContentAccess(false);
294
295        // HTML5 API flags
296        settings.setAppCacheEnabled(true);
297        settings.setDatabaseEnabled(true);
298        settings.setDomStorageEnabled(true);
299
300        // HTML5 configuration parametersettings.
301        settings.setAppCacheMaxSize(getWebStorageSizeManager().getAppCacheMaxSize());
302        settings.setAppCachePath(getAppCachePath());
303        settings.setDatabasePath(mContext.getDir("databases", 0).getPath());
304        settings.setGeolocationDatabasePath(mContext.getDir("geolocation", 0).getPath());
305        // origin policy for file access
306        settings.setAllowUniversalAccessFromFileURLs(false);
307        settings.setAllowFileAccessFromFileURLs(false);
308    }
309
310    private void syncSharedSettings() {
311        mNeedsSharedSync = false;
312        CookieManager.getInstance().setAcceptCookie(acceptCookies());
313        if (mController != null) {
314            mController.setShouldShowErrorConsole(enableJavascriptConsole());
315        }
316    }
317
318    private void syncManagedSettings() {
319        syncSharedSettings();
320        synchronized (mManagedSettings) {
321            Iterator<WeakReference<WebSettings>> iter = mManagedSettings.iterator();
322            while (iter.hasNext()) {
323                WeakReference<WebSettings> ref = iter.next();
324                WebSettings settings = ref.get();
325                if (settings == null) {
326                    iter.remove();
327                    continue;
328                }
329                syncSetting(settings);
330            }
331        }
332    }
333
334    @Override
335    public void onSharedPreferenceChanged(
336            SharedPreferences sharedPreferences, String key) {
337        syncManagedSettings();
338        if (PREF_SEARCH_ENGINE.equals(key)) {
339            updateSearchEngine(false);
340        } else if (PREF_FULLSCREEN.equals(key)) {
341            if (mController != null && mController.getUi() != null) {
342                mController.getUi().setFullscreen(useFullscreen());
343            }
344        } else if (PREF_ENABLE_QUICK_CONTROLS.equals(key)) {
345            if (mController != null && mController.getUi() != null) {
346                mController.getUi().setUseQuickControls(sharedPreferences.getBoolean(key, false));
347            }
348        } else if (PREF_LINK_PREFETCH.equals(key)) {
349            updateConnectionType();
350        }
351    }
352
353    public static String getFactoryResetHomeUrl(Context context) {
354        requireInitialization();
355        return sFactoryResetUrl;
356    }
357
358    public LayoutAlgorithm getLayoutAlgorithm() {
359        LayoutAlgorithm layoutAlgorithm = LayoutAlgorithm.NORMAL;
360        if (autofitPages()) {
361            layoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
362        }
363        if (isDebugEnabled()) {
364            if (isSmallScreen()) {
365                layoutAlgorithm = LayoutAlgorithm.SINGLE_COLUMN;
366            } else {
367                if (isNormalLayout()) {
368                    layoutAlgorithm = LayoutAlgorithm.NORMAL;
369                } else {
370                    layoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
371                }
372            }
373        }
374        return layoutAlgorithm;
375    }
376
377    public int getPageCacheCapacity() {
378        requireInitialization();
379        return mPageCacheCapacity;
380    }
381
382    public WebStorageSizeManager getWebStorageSizeManager() {
383        requireInitialization();
384        return mWebStorageSizeManager;
385    }
386
387    private String getAppCachePath() {
388        if (mAppCachePath == null) {
389            mAppCachePath = mContext.getDir("appcache", 0).getPath();
390        }
391        return mAppCachePath;
392    }
393
394    private void updateSearchEngine(boolean force) {
395        String searchEngineName = getSearchEngineName();
396        if (force || mSearchEngine == null ||
397                !mSearchEngine.getName().equals(searchEngineName)) {
398            mSearchEngine = SearchEngines.get(mContext, searchEngineName);
399         }
400    }
401
402    public SearchEngine getSearchEngine() {
403        if (mSearchEngine == null) {
404            updateSearchEngine(false);
405        }
406        return mSearchEngine;
407    }
408
409    public boolean isDebugEnabled() {
410        requireInitialization();
411        return mPrefs.getBoolean(PREF_DEBUG_MENU, false);
412    }
413
414    public void setDebugEnabled(boolean value) {
415        Editor edit = mPrefs.edit();
416        edit.putBoolean(PREF_DEBUG_MENU, value);
417        if (!value) {
418            // Reset to "safe" value
419            edit.putBoolean(PREF_ENABLE_HARDWARE_ACCEL_SKIA, false);
420        }
421        edit.apply();
422    }
423
424    public void clearCache() {
425        WebIconDatabase.getInstance().removeAllIcons();
426        if (mController != null) {
427            WebView current = mController.getCurrentWebView();
428            if (current != null) {
429                current.clearCache(true);
430            }
431        }
432    }
433
434    public void clearCookies() {
435        CookieManager.getInstance().removeAllCookie();
436    }
437
438    public void clearHistory() {
439        ContentResolver resolver = mContext.getContentResolver();
440        Browser.clearHistory(resolver);
441        Browser.clearSearches(resolver);
442    }
443
444    public void clearFormData() {
445        WebViewDatabase.getInstance(mContext).clearFormData();
446        if (mController!= null) {
447            WebView currentTopView = mController.getCurrentTopWebView();
448            if (currentTopView != null) {
449                currentTopView.clearFormData();
450            }
451        }
452    }
453
454    public void clearPasswords() {
455        WebViewDatabase db = WebViewDatabase.getInstance(mContext);
456        db.clearUsernamePassword();
457        db.clearHttpAuthUsernamePassword();
458    }
459
460    public void clearDatabases() {
461        WebStorage.getInstance().deleteAllData();
462    }
463
464    public void clearLocationAccess() {
465        GeolocationPermissions.getInstance().clearAll();
466    }
467
468    public void resetDefaultPreferences() {
469        // Preserve autologin setting
470        long gal = mPrefs.getLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, -1);
471        mPrefs.edit()
472                .clear()
473                .putLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, gal)
474                .apply();
475        resetCachedValues();
476        syncManagedSettings();
477    }
478
479    private void resetCachedValues() {
480        updateSearchEngine(false);
481    }
482
483    public void toggleDebugSettings() {
484        setDebugEnabled(!isDebugEnabled());
485    }
486
487    public boolean hasDesktopUseragent(WebView view) {
488        return view != null && mCustomUserAgents.get(view.getSettings()) != null;
489    }
490
491    public void toggleDesktopUseragent(WebView view) {
492        if (view == null) {
493            return;
494        }
495        WebSettings settings = view.getSettings();
496        if (mCustomUserAgents.get(settings) != null) {
497            mCustomUserAgents.remove(settings);
498            settings.setUserAgentString(USER_AGENTS[getUserAgent()]);
499        } else {
500            mCustomUserAgents.put(settings, DESKTOP_USERAGENT);
501            settings.setUserAgentString(DESKTOP_USERAGENT);
502        }
503    }
504
505    public static int getAdjustedMinimumFontSize(int rawValue) {
506        rawValue++; // Preference starts at 0, min font at 1
507        if (rawValue > 1) {
508            rawValue += (MIN_FONT_SIZE_OFFSET - 2);
509        }
510        return rawValue;
511    }
512
513    public int getAdjustedTextZoom(int rawValue) {
514        rawValue = (rawValue - TEXT_ZOOM_START_VAL) * TEXT_ZOOM_STEP;
515        return (int) ((rawValue + 100) * mFontSizeMult);
516    }
517
518    static int getRawTextZoom(int percent) {
519        return (percent - 100) / TEXT_ZOOM_STEP + TEXT_ZOOM_START_VAL;
520    }
521
522    public int getAdjustedDoubleTapZoom(int rawValue) {
523        rawValue = (rawValue - DOUBLE_TAP_ZOOM_START_VAL) * DOUBLE_TAP_ZOOM_STEP;
524        return (int) ((rawValue + 100) * mFontSizeMult);
525    }
526
527    static int getRawDoubleTapZoom(int percent) {
528        return (percent - 100) / DOUBLE_TAP_ZOOM_STEP + DOUBLE_TAP_ZOOM_START_VAL;
529    }
530
531    public SharedPreferences getPreferences() {
532        return mPrefs;
533    }
534
535    // update connectivity-dependent options
536    public void updateConnectionType() {
537        ConnectivityManager cm = (ConnectivityManager)
538            mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
539        String linkPrefetchPreference = getLinkPrefetchEnabled();
540        boolean linkPrefetchAllowed = linkPrefetchPreference.
541            equals(getLinkPrefetchAlwaysPreferenceString(mContext));
542        NetworkInfo ni = cm.getActiveNetworkInfo();
543        if (ni != null) {
544            switch (ni.getType()) {
545                case ConnectivityManager.TYPE_WIFI:
546                case ConnectivityManager.TYPE_ETHERNET:
547                case ConnectivityManager.TYPE_BLUETOOTH:
548                    linkPrefetchAllowed |= linkPrefetchPreference.
549                        equals(getLinkPrefetchOnWifiOnlyPreferenceString(mContext));
550                    break;
551                case ConnectivityManager.TYPE_MOBILE:
552                case ConnectivityManager.TYPE_MOBILE_DUN:
553                case ConnectivityManager.TYPE_MOBILE_MMS:
554                case ConnectivityManager.TYPE_MOBILE_SUPL:
555                case ConnectivityManager.TYPE_WIMAX:
556                default:
557                    break;
558            }
559        }
560        if (mLinkPrefetchAllowed != linkPrefetchAllowed) {
561            mLinkPrefetchAllowed = linkPrefetchAllowed;
562            syncManagedSettings();
563        }
564    }
565
566    // -----------------------------
567    // getter/setters for accessibility_preferences.xml
568    // -----------------------------
569
570    @Deprecated
571    private TextSize getTextSize() {
572        String textSize = mPrefs.getString(PREF_TEXT_SIZE, "NORMAL");
573        return TextSize.valueOf(textSize);
574    }
575
576    public int getMinimumFontSize() {
577        int minFont = mPrefs.getInt(PREF_MIN_FONT_SIZE, 0);
578        return getAdjustedMinimumFontSize(minFont);
579    }
580
581    public boolean forceEnableUserScalable() {
582        return mPrefs.getBoolean(PREF_FORCE_USERSCALABLE, false);
583    }
584
585    public int getTextZoom() {
586        requireInitialization();
587        int textZoom = mPrefs.getInt(PREF_TEXT_ZOOM, 10);
588        return getAdjustedTextZoom(textZoom);
589    }
590
591    public void setTextZoom(int percent) {
592        mPrefs.edit().putInt(PREF_TEXT_ZOOM, getRawTextZoom(percent)).apply();
593    }
594
595    public int getDoubleTapZoom() {
596        requireInitialization();
597        int doubleTapZoom = mPrefs.getInt(PREF_DOUBLE_TAP_ZOOM, 5);
598        return getAdjustedDoubleTapZoom(doubleTapZoom);
599    }
600
601    public void setDoubleTapZoom(int percent) {
602        mPrefs.edit().putInt(PREF_DOUBLE_TAP_ZOOM, getRawDoubleTapZoom(percent)).apply();
603    }
604
605    // -----------------------------
606    // getter/setters for advanced_preferences.xml
607    // -----------------------------
608
609    public String getSearchEngineName() {
610        return mPrefs.getString(PREF_SEARCH_ENGINE, SearchEngine.GOOGLE);
611    }
612
613    public boolean allowAppTabs() {
614        return mPrefs.getBoolean(PREF_ALLOW_APP_TABS, false);
615    }
616
617    public boolean openInBackground() {
618        return mPrefs.getBoolean(PREF_OPEN_IN_BACKGROUND, false);
619    }
620
621    public boolean enableJavascript() {
622        return mPrefs.getBoolean(PREF_ENABLE_JAVASCRIPT, true);
623    }
624
625    // TODO: Cache
626    public PluginState getPluginState() {
627        String state = mPrefs.getString(PREF_PLUGIN_STATE, "ON");
628        return PluginState.valueOf(state);
629    }
630
631    // TODO: Cache
632    public ZoomDensity getDefaultZoom() {
633        String zoom = mPrefs.getString(PREF_DEFAULT_ZOOM, "MEDIUM");
634        return ZoomDensity.valueOf(zoom);
635    }
636
637    public boolean loadPageInOverviewMode() {
638        return mPrefs.getBoolean(PREF_LOAD_PAGE, true);
639    }
640
641    public boolean autofitPages() {
642        return mPrefs.getBoolean(PREF_AUTOFIT_PAGES, true);
643    }
644
645    public boolean blockPopupWindows() {
646        return mPrefs.getBoolean(PREF_BLOCK_POPUP_WINDOWS, true);
647    }
648
649    public boolean loadImages() {
650        return mPrefs.getBoolean(PREF_LOAD_IMAGES, true);
651    }
652
653    public String getDefaultTextEncoding() {
654        return mPrefs.getString(PREF_DEFAULT_TEXT_ENCODING, null);
655    }
656
657    // -----------------------------
658    // getter/setters for general_preferences.xml
659    // -----------------------------
660
661    public String getHomePage() {
662        return mPrefs.getString(PREF_HOMEPAGE, getFactoryResetHomeUrl(mContext));
663    }
664
665    public void setHomePage(String value) {
666        mPrefs.edit().putString(PREF_HOMEPAGE, value).apply();
667    }
668
669    public boolean isAutofillEnabled() {
670        return mPrefs.getBoolean(PREF_AUTOFILL_ENABLED, true);
671    }
672
673    public void setAutofillEnabled(boolean value) {
674        mPrefs.edit().putBoolean(PREF_AUTOFILL_ENABLED, value).apply();
675    }
676
677    // -----------------------------
678    // getter/setters for debug_preferences.xml
679    // -----------------------------
680
681    public boolean isHardwareAccelerated() {
682        if (!isDebugEnabled()) {
683            return true;
684        }
685        return mPrefs.getBoolean(PREF_ENABLE_HARDWARE_ACCEL, true);
686    }
687
688    public boolean isSkiaHardwareAccelerated() {
689        if (!isDebugEnabled()) {
690            return false;
691        }
692        return mPrefs.getBoolean(PREF_ENABLE_HARDWARE_ACCEL_SKIA, false);
693    }
694
695    public int getUserAgent() {
696        if (!isDebugEnabled()) {
697            return 0;
698        }
699        return Integer.parseInt(mPrefs.getString(PREF_USER_AGENT, "0"));
700    }
701
702    // -----------------------------
703    // getter/setters for hidden_debug_preferences.xml
704    // -----------------------------
705
706    public boolean enableVisualIndicator() {
707        if (!isDebugEnabled()) {
708            return false;
709        }
710        return mPrefs.getBoolean(PREF_ENABLE_VISUAL_INDICATOR, false);
711    }
712
713    public boolean enableCpuUploadPath() {
714        if (!isDebugEnabled()) {
715            return false;
716        }
717        return mPrefs.getBoolean(PREF_ENABLE_CPU_UPLOAD_PATH, false);
718    }
719
720    public boolean enableJavascriptConsole() {
721        if (!isDebugEnabled()) {
722            return false;
723        }
724        return mPrefs.getBoolean(PREF_JAVASCRIPT_CONSOLE, true);
725    }
726
727    public boolean isSmallScreen() {
728        if (!isDebugEnabled()) {
729            return false;
730        }
731        return mPrefs.getBoolean(PREF_SMALL_SCREEN, false);
732    }
733
734    public boolean isWideViewport() {
735        if (!isDebugEnabled()) {
736            return true;
737        }
738        return mPrefs.getBoolean(PREF_WIDE_VIEWPORT, true);
739    }
740
741    public boolean isNormalLayout() {
742        if (!isDebugEnabled()) {
743            return false;
744        }
745        return mPrefs.getBoolean(PREF_NORMAL_LAYOUT, false);
746    }
747
748    public boolean isTracing() {
749        if (!isDebugEnabled()) {
750            return false;
751        }
752        return mPrefs.getBoolean(PREF_ENABLE_TRACING, false);
753    }
754
755    public boolean enableLightTouch() {
756        if (!isDebugEnabled()) {
757            return false;
758        }
759        return mPrefs.getBoolean(PREF_ENABLE_LIGHT_TOUCH, false);
760    }
761
762    public boolean enableNavDump() {
763        if (!isDebugEnabled()) {
764            return false;
765        }
766        return mPrefs.getBoolean(PREF_ENABLE_NAV_DUMP, false);
767    }
768
769    public String getJsEngineFlags() {
770        if (!isDebugEnabled()) {
771            return "";
772        }
773        return mPrefs.getString(PREF_JS_ENGINE_FLAGS, "");
774    }
775
776    // -----------------------------
777    // getter/setters for lab_preferences.xml
778    // -----------------------------
779
780    public boolean useQuickControls() {
781        return mPrefs.getBoolean(PREF_ENABLE_QUICK_CONTROLS, false);
782    }
783
784    public boolean useMostVisitedHomepage() {
785        return HomeProvider.MOST_VISITED.equals(getHomePage());
786    }
787
788    public boolean useFullscreen() {
789        return mPrefs.getBoolean(PREF_FULLSCREEN, false);
790    }
791
792    public boolean useInvertedRendering() {
793        return mPrefs.getBoolean(PREF_INVERTED, false);
794    }
795
796    public float getInvertedContrast() {
797        return 1 + (mPrefs.getInt(PREF_INVERTED_CONTRAST, 0) / 10f);
798    }
799
800    // -----------------------------
801    // getter/setters for privacy_security_preferences.xml
802    // -----------------------------
803
804    public boolean showSecurityWarnings() {
805        return mPrefs.getBoolean(PREF_SHOW_SECURITY_WARNINGS, true);
806    }
807
808    public boolean acceptCookies() {
809        return mPrefs.getBoolean(PREF_ACCEPT_COOKIES, true);
810    }
811
812    public boolean saveFormdata() {
813        return mPrefs.getBoolean(PREF_SAVE_FORMDATA, true);
814    }
815
816    public boolean enableGeolocation() {
817        return mPrefs.getBoolean(PREF_ENABLE_GEOLOCATION, true);
818    }
819
820    public boolean rememberPasswords() {
821        return mPrefs.getBoolean(PREF_REMEMBER_PASSWORDS, true);
822    }
823
824    // -----------------------------
825    // getter/setters for bandwidth_preferences.xml
826    // -----------------------------
827
828    public static String getPreloadOnWifiOnlyPreferenceString(Context context) {
829        return context.getResources().getString(R.string.pref_data_preload_value_wifi_only);
830    }
831
832    public static String getPreloadAlwaysPreferenceString(Context context) {
833        return context.getResources().getString(R.string.pref_data_preload_value_always);
834    }
835
836    private static final String DEAULT_PRELOAD_SECURE_SETTING_KEY =
837            "browser_default_preload_setting";
838
839    public String getDefaultPreloadSetting() {
840        String preload = Settings.Secure.getString(mContext.getContentResolver(),
841                DEAULT_PRELOAD_SECURE_SETTING_KEY);
842        if (preload == null) {
843            preload = mContext.getResources().getString(R.string.pref_data_preload_default_value);
844        }
845        return preload;
846    }
847
848    public String getPreloadEnabled() {
849        return mPrefs.getString(PREF_DATA_PRELOAD, getDefaultPreloadSetting());
850    }
851
852    public static String getLinkPrefetchOnWifiOnlyPreferenceString(Context context) {
853        return context.getResources().getString(R.string.pref_link_prefetch_value_wifi_only);
854    }
855
856    public static String getLinkPrefetchAlwaysPreferenceString(Context context) {
857        return context.getResources().getString(R.string.pref_link_prefetch_value_always);
858    }
859
860    private static final String DEFAULT_LINK_PREFETCH_SECURE_SETTING_KEY =
861            "browser_default_link_prefetch_setting";
862
863    public String getDefaultLinkPrefetchSetting() {
864        String preload = Settings.Secure.getString(mContext.getContentResolver(),
865            DEFAULT_LINK_PREFETCH_SECURE_SETTING_KEY);
866        if (preload == null) {
867            preload = mContext.getResources().getString(R.string.pref_link_prefetch_default_value);
868        }
869        return preload;
870    }
871
872    public String getLinkPrefetchEnabled() {
873        return mPrefs.getString(PREF_LINK_PREFETCH, getDefaultLinkPrefetchSetting());
874    }
875
876    // -----------------------------
877    // getter/setters for browser recovery
878    // -----------------------------
879    /**
880     * The last time browser was started.
881     * @return The last browser start time as System.currentTimeMillis. This
882     * can be 0 if this is the first time or the last tab was closed.
883     */
884    public long getLastRecovered() {
885        return mPrefs.getLong(KEY_LAST_RECOVERED, 0);
886    }
887
888    /**
889     * Sets the last browser start time.
890     * @param time The last time as System.currentTimeMillis that the browser
891     * was started. This should be set to 0 if the last tab is closed.
892     */
893    public void setLastRecovered(long time) {
894        mPrefs.edit()
895            .putLong(KEY_LAST_RECOVERED, time)
896            .apply();
897    }
898
899    /**
900     * Used to determine whether or not the previous browser run crashed. Once
901     * the previous state has been determined, the value will be set to false
902     * until a pause is received.
903     * @return true if the last browser run was paused or false if it crashed.
904     */
905    public boolean wasLastRunPaused() {
906        return mPrefs.getBoolean(KEY_LAST_RUN_PAUSED, false);
907    }
908
909    /**
910     * Sets whether or not the last run was a pause or crash.
911     * @param isPaused Set to true When a pause is received or false after
912     * resuming.
913     */
914    public void setLastRunPaused(boolean isPaused) {
915        mPrefs.edit()
916            .putBoolean(KEY_LAST_RUN_PAUSED, isPaused)
917            .apply();
918    }
919}
920