Home | History | Annotate | Download | only in browser
      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 
     17 package com.android.browser;
     18 
     19 import android.app.ActivityManager;
     20 import android.content.ContentResolver;
     21 import android.content.Context;
     22 import android.content.SharedPreferences;
     23 import android.content.SharedPreferences.Editor;
     24 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
     25 import android.net.ConnectivityManager;
     26 import android.net.NetworkInfo;
     27 import android.os.Build;
     28 import android.os.Message;
     29 import android.preference.PreferenceManager;
     30 import android.provider.Browser;
     31 import android.provider.Settings;
     32 import android.util.DisplayMetrics;
     33 import android.webkit.CookieManager;
     34 import android.webkit.GeolocationPermissions;
     35 import android.webkit.WebIconDatabase;
     36 import android.webkit.WebSettings;
     37 import android.webkit.WebSettings.LayoutAlgorithm;
     38 import android.webkit.WebSettings.PluginState;
     39 import android.webkit.WebSettings.TextSize;
     40 import android.webkit.WebSettings.ZoomDensity;
     41 import android.webkit.WebStorage;
     42 import android.webkit.WebView;
     43 import android.webkit.WebViewDatabase;
     44 
     45 import com.android.browser.homepages.HomeProvider;
     46 import com.android.browser.provider.BrowserProvider;
     47 import com.android.browser.search.SearchEngine;
     48 import com.android.browser.search.SearchEngines;
     49 
     50 import java.lang.ref.WeakReference;
     51 import java.util.Iterator;
     52 import java.util.LinkedList;
     53 import java.util.WeakHashMap;
     54 
     55 /**
     56  * Class for managing settings
     57  */
     58 public 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