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