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 
    151     public void startManagingSettings(WebSettings settings) {
    152         if (mNeedsSharedSync) {
    153             syncSharedSettings();
    154         }
    155         synchronized (mManagedSettings) {
    156             syncStaticSettings(settings);
    157             syncSetting(settings);
    158             mManagedSettings.add(new WeakReference<WebSettings>(settings));
    159         }
    160     }
    161 
    162     private Runnable mSetup = new Runnable() {
    163 
    164         @Override
    165         public void run() {
    166             DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
    167             mFontSizeMult = metrics.scaledDensity / metrics.density;
    168             // the cost of one cached page is ~3M (measured using nytimes.com). For
    169             // low end devices, we only cache one page. For high end devices, we try
    170             // to cache more pages, currently choose 5.
    171             if (ActivityManager.staticGetMemoryClass() > 16) {
    172                 mPageCacheCapacity = 5;
    173             }
    174             mWebStorageSizeManager = new WebStorageSizeManager(mContext,
    175                     new WebStorageSizeManager.StatFsDiskInfo(getAppCachePath()),
    176                     new WebStorageSizeManager.WebKitAppCacheInfo(getAppCachePath()));
    177             // Workaround b/5253777
    178             CookieManager.getInstance().acceptCookie();
    179             // Workaround b/5254577
    180             mPrefs.registerOnSharedPreferenceChangeListener(BrowserSettings.this);
    181             if (Build.VERSION.CODENAME.equals("REL")) {
    182                 // This is a release build, always startup with debug disabled
    183                 setDebugEnabled(false);
    184             }
    185             if (mPrefs.contains(PREF_TEXT_SIZE)) {
    186                 /*
    187                  * Update from TextSize enum to zoom percent
    188                  * SMALLEST is 50%
    189                  * SMALLER is 75%
    190                  * NORMAL is 100%
    191                  * LARGER is 150%
    192                  * LARGEST is 200%
    193                  */
    194                 switch (getTextSize()) {
    195                 case SMALLEST:
    196                     setTextZoom(50);
    197                     break;
    198                 case SMALLER:
    199                     setTextZoom(75);
    200                     break;
    201                 case LARGER:
    202                     setTextZoom(150);
    203                     break;
    204                 case LARGEST:
    205                     setTextZoom(200);
    206                     break;
    207                 }
    208                 mPrefs.edit().remove(PREF_TEXT_SIZE).apply();
    209             }
    210 
    211             sFactoryResetUrl = mContext.getResources().getString(R.string.homepage_base);
    212             if (sFactoryResetUrl.indexOf("{CID}") != -1) {
    213                 sFactoryResetUrl = sFactoryResetUrl.replace("{CID}",
    214                     BrowserProvider.getClientId(mContext.getContentResolver()));
    215             }
    216 
    217             synchronized (BrowserSettings.class) {
    218                 sInitialized = true;
    219                 BrowserSettings.class.notifyAll();
    220             }
    221         }
    222     };
    223 
    224     private static void requireInitialization() {
    225         synchronized (BrowserSettings.class) {
    226             while (!sInitialized) {
    227                 try {
    228                     BrowserSettings.class.wait();
    229                 } catch (InterruptedException e) {
    230                 }
    231             }
    232         }
    233     }
    234 
    235     /**
    236      * Syncs all the settings that have a Preference UI
    237      */
    238     private void syncSetting(WebSettings settings) {
    239         settings.setGeolocationEnabled(enableGeolocation());
    240         settings.setJavaScriptEnabled(enableJavascript());
    241         settings.setLightTouchEnabled(enableLightTouch());
    242         settings.setNavDump(enableNavDump());
    243         settings.setHardwareAccelSkiaEnabled(isSkiaHardwareAccelerated());
    244         settings.setShowVisualIndicator(enableVisualIndicator());
    245         settings.setDefaultTextEncodingName(getDefaultTextEncoding());
    246         settings.setDefaultZoom(getDefaultZoom());
    247         settings.setMinimumFontSize(getMinimumFontSize());
    248         settings.setMinimumLogicalFontSize(getMinimumFontSize());
    249         settings.setForceUserScalable(forceEnableUserScalable());
    250         settings.setPluginState(getPluginState());
    251         settings.setTextZoom(getTextZoom());
    252         settings.setDoubleTapZoom(getDoubleTapZoom());
    253         settings.setAutoFillEnabled(isAutofillEnabled());
    254         settings.setLayoutAlgorithm(getLayoutAlgorithm());
    255         settings.setJavaScriptCanOpenWindowsAutomatically(!blockPopupWindows());
    256         settings.setLoadsImagesAutomatically(loadImages());
    257         settings.setLoadWithOverviewMode(loadPageInOverviewMode());
    258         settings.setSavePassword(rememberPasswords());
    259         settings.setSaveFormData(saveFormdata());
    260         settings.setUseWideViewPort(isWideViewport());
    261         settings.setAutoFillProfile(getAutoFillProfile());
    262 
    263         String ua = mCustomUserAgents.get(settings);
    264         if (ua != null) {
    265             settings.setUserAgentString(ua);
    266         } else {
    267             settings.setUserAgentString(USER_AGENTS[getUserAgent()]);
    268         }
    269 
    270         boolean useInverted = useInvertedRendering();
    271         settings.setProperty(WebViewProperties.gfxInvertedScreen,
    272                 useInverted ? "true" : "false");
    273         if (useInverted) {
    274             settings.setProperty(WebViewProperties.gfxInvertedScreenContrast,
    275                     Float.toString(getInvertedContrast()));
    276         }
    277 
    278         if (isDebugEnabled()) {
    279             settings.setProperty(WebViewProperties.gfxEnableCpuUploadPath,
    280                     enableCpuUploadPath() ? "true" : "false");
    281         }
    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         // WebView should be preserving the memory as much as possible.
    301         // However, apps like browser wish to turn on the performance mode which
    302         // would require more memory.
    303         // TODO: We need to dynamically allocate/deallocate temporary memory for
    304         // apps which are trying to use minimal memory. Currently, double
    305         // buffering is always turned on, which is unnecessary.
    306         settings.setProperty(WebViewProperties.gfxUseMinimalMemory, "false");
    307         // disable content url access
    308         settings.setAllowContentAccess(false);
    309 
    310         // HTML5 API flags
    311         settings.setAppCacheEnabled(true);
    312         settings.setDatabaseEnabled(true);
    313         settings.setDomStorageEnabled(true);
    314         settings.setWorkersEnabled(true);  // This only affects V8.
    315 
    316         // HTML5 configuration parametersettings.
    317         settings.setAppCacheMaxSize(getWebStorageSizeManager().getAppCacheMaxSize());
    318         settings.setAppCachePath(getAppCachePath());
    319         settings.setDatabasePath(mContext.getDir("databases", 0).getPath());
    320         settings.setGeolocationDatabasePath(mContext.getDir("geolocation", 0).getPath());
    321     }
    322 
    323     private void syncSharedSettings() {
    324         mNeedsSharedSync = false;
    325         CookieManager.getInstance().setAcceptCookie(acceptCookies());
    326         if (mController != null) {
    327             mController.setShouldShowErrorConsole(enableJavascriptConsole());
    328         }
    329     }
    330 
    331     private void syncManagedSettings() {
    332         syncSharedSettings();
    333         synchronized (mManagedSettings) {
    334             Iterator<WeakReference<WebSettings>> iter = mManagedSettings.iterator();
    335             while (iter.hasNext()) {
    336                 WeakReference<WebSettings> ref = iter.next();
    337                 WebSettings settings = ref.get();
    338                 if (settings == null) {
    339                     iter.remove();
    340                     continue;
    341                 }
    342                 syncSetting(settings);
    343             }
    344         }
    345     }
    346 
    347     @Override
    348     public void onSharedPreferenceChanged(
    349             SharedPreferences sharedPreferences, String key) {
    350         syncManagedSettings();
    351         if (PREF_SEARCH_ENGINE.equals(key)) {
    352             updateSearchEngine(false);
    353         }
    354         if (PREF_FULLSCREEN.equals(key)) {
    355             if (mController.getUi() != null) {
    356                 mController.getUi().setFullscreen(useFullscreen());
    357             }
    358         } else if (PREF_ENABLE_QUICK_CONTROLS.equals(key)) {
    359             if (mController.getUi() != null) {
    360                 mController.getUi().setUseQuickControls(sharedPreferences.getBoolean(key, false));
    361             }
    362         }
    363     }
    364 
    365     public static String getFactoryResetHomeUrl(Context context) {
    366         requireInitialization();
    367         return sFactoryResetUrl;
    368     }
    369 
    370     public LayoutAlgorithm getLayoutAlgorithm() {
    371         LayoutAlgorithm layoutAlgorithm = LayoutAlgorithm.NORMAL;
    372         if (autofitPages()) {
    373             layoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
    374         }
    375         if (isDebugEnabled()) {
    376             if (isSmallScreen()) {
    377                 layoutAlgorithm = LayoutAlgorithm.SINGLE_COLUMN;
    378             } else {
    379                 if (isNormalLayout()) {
    380                     layoutAlgorithm = LayoutAlgorithm.NORMAL;
    381                 } else {
    382                     layoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
    383                 }
    384             }
    385         }
    386         return layoutAlgorithm;
    387     }
    388 
    389     public int getPageCacheCapacity() {
    390         requireInitialization();
    391         return mPageCacheCapacity;
    392     }
    393 
    394     public WebStorageSizeManager getWebStorageSizeManager() {
    395         requireInitialization();
    396         return mWebStorageSizeManager;
    397     }
    398 
    399     private String getAppCachePath() {
    400         if (mAppCachePath == null) {
    401             mAppCachePath = mContext.getDir("appcache", 0).getPath();
    402         }
    403         return mAppCachePath;
    404     }
    405 
    406     private void updateSearchEngine(boolean force) {
    407         String searchEngineName = getSearchEngineName();
    408         if (force || mSearchEngine == null ||
    409                 !mSearchEngine.getName().equals(searchEngineName)) {
    410             if (mSearchEngine != null) {
    411                 if (mSearchEngine.supportsVoiceSearch()) {
    412                      // One or more tabs could have been in voice search mode.
    413                      // Clear it, since the new SearchEngine may not support
    414                      // it, or may handle it differently.
    415                      for (int i = 0; i < mController.getTabControl().getTabCount(); i++) {
    416                          mController.getTabControl().getTab(i).revertVoiceSearchMode();
    417                      }
    418                  }
    419                 mSearchEngine.close();
    420              }
    421             mSearchEngine = SearchEngines.get(mContext, searchEngineName);
    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 useFullscreen() {
    787         return mPrefs.getBoolean(PREF_FULLSCREEN, false);
    788     }
    789 
    790     public boolean useInvertedRendering() {
    791         return mPrefs.getBoolean(PREF_INVERTED, false);
    792     }
    793 
    794     public float getInvertedContrast() {
    795         return 1 + (mPrefs.getInt(PREF_INVERTED_CONTRAST, 0) / 10f);
    796     }
    797 
    798     // -----------------------------
    799     // getter/setters for privacy_security_preferences.xml
    800     // -----------------------------
    801 
    802     public boolean showSecurityWarnings() {
    803         return mPrefs.getBoolean(PREF_SHOW_SECURITY_WARNINGS, true);
    804     }
    805 
    806     public boolean acceptCookies() {
    807         return mPrefs.getBoolean(PREF_ACCEPT_COOKIES, true);
    808     }
    809 
    810     public boolean saveFormdata() {
    811         return mPrefs.getBoolean(PREF_SAVE_FORMDATA, true);
    812     }
    813 
    814     public boolean enableGeolocation() {
    815         return mPrefs.getBoolean(PREF_ENABLE_GEOLOCATION, true);
    816     }
    817 
    818     public boolean rememberPasswords() {
    819         return mPrefs.getBoolean(PREF_REMEMBER_PASSWORDS, true);
    820     }
    821 
    822     // -----------------------------
    823     // getter/setters for bandwidth_preferences.xml
    824     // -----------------------------
    825 
    826     public static String getPreloadOnWifiOnlyPreferenceString(Context context) {
    827         return context.getResources().getString(R.string.pref_data_preload_value_wifi_only);
    828     }
    829 
    830     public static String getPreloadAlwaysPreferenceString(Context context) {
    831         return context.getResources().getString(R.string.pref_data_preload_value_always);
    832     }
    833 
    834     private static final String DEAULT_PRELOAD_SECURE_SETTING_KEY =
    835             "browser_default_preload_setting";
    836 
    837     public String getDefaultPreloadSetting() {
    838         String preload = Settings.Secure.getString(mContext.getContentResolver(),
    839                 DEAULT_PRELOAD_SECURE_SETTING_KEY);
    840         if (preload == null) {
    841             preload = mContext.getResources().getString(R.string.pref_data_preload_default_value);
    842         }
    843         return preload;
    844     }
    845 
    846     public String getPreloadEnabled() {
    847         return mPrefs.getString(PREF_DATA_PRELOAD, getDefaultPreloadSetting());
    848     }
    849 
    850 }
    851