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 
initialize(final Context context)129     public static void initialize(final Context context) {
130         sInstance = new BrowserSettings(context);
131     }
132 
getInstance()133     public static BrowserSettings getInstance() {
134         return sInstance;
135     }
136 
BrowserSettings(Context context)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 
setController(Controller controller)145     public void setController(Controller controller) {
146         mController = controller;
147         if (sInitialized) {
148             syncSharedSettings();
149         }
150     }
151 
startManagingSettings(WebSettings settings)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 
stopManagingSettings(WebSettings settings)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 
requireInitialization()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      */
syncSetting(WebSettings settings)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      */
syncStaticSettings(WebSettings settings)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 
syncSharedSettings()310     private void syncSharedSettings() {
311         mNeedsSharedSync = false;
312         CookieManager.getInstance().setAcceptCookie(acceptCookies());
313         if (mController != null) {
314             for (Tab tab : mController.getTabs()) {
315                 tab.setAcceptThirdPartyCookies(acceptCookies());
316             }
317             mController.setShouldShowErrorConsole(enableJavascriptConsole());
318         }
319     }
320 
syncManagedSettings()321     private void syncManagedSettings() {
322         syncSharedSettings();
323         synchronized (mManagedSettings) {
324             Iterator<WeakReference<WebSettings>> iter = mManagedSettings.iterator();
325             while (iter.hasNext()) {
326                 WeakReference<WebSettings> ref = iter.next();
327                 WebSettings settings = ref.get();
328                 if (settings == null) {
329                     iter.remove();
330                     continue;
331                 }
332                 syncSetting(settings);
333             }
334         }
335     }
336 
337     @Override
onSharedPreferenceChanged( SharedPreferences sharedPreferences, String key)338     public void onSharedPreferenceChanged(
339             SharedPreferences sharedPreferences, String key) {
340         syncManagedSettings();
341         if (PREF_SEARCH_ENGINE.equals(key)) {
342             updateSearchEngine(false);
343         } else if (PREF_FULLSCREEN.equals(key)) {
344             if (mController != null && mController.getUi() != null) {
345                 mController.getUi().setFullscreen(useFullscreen());
346             }
347         } else if (PREF_ENABLE_QUICK_CONTROLS.equals(key)) {
348             if (mController != null && mController.getUi() != null) {
349                 mController.getUi().setUseQuickControls(sharedPreferences.getBoolean(key, false));
350             }
351         } else if (PREF_LINK_PREFETCH.equals(key)) {
352             updateConnectionType();
353         }
354     }
355 
getFactoryResetHomeUrl(Context context)356     public static String getFactoryResetHomeUrl(Context context) {
357         requireInitialization();
358         return sFactoryResetUrl;
359     }
360 
getLayoutAlgorithm()361     public LayoutAlgorithm getLayoutAlgorithm() {
362         LayoutAlgorithm layoutAlgorithm = LayoutAlgorithm.NORMAL;
363         final LayoutAlgorithm autosize = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ?
364                 LayoutAlgorithm.TEXT_AUTOSIZING : LayoutAlgorithm.NARROW_COLUMNS;
365 
366         if (autofitPages()) {
367             layoutAlgorithm = autosize;
368         }
369         if (isDebugEnabled()) {
370             if (isNormalLayout()) {
371                 layoutAlgorithm = LayoutAlgorithm.NORMAL;
372             } else {
373                 layoutAlgorithm = autosize;
374             }
375         }
376         return layoutAlgorithm;
377     }
378 
getPageCacheCapacity()379     public int getPageCacheCapacity() {
380         requireInitialization();
381         return mPageCacheCapacity;
382     }
383 
getWebStorageSizeManager()384     public WebStorageSizeManager getWebStorageSizeManager() {
385         requireInitialization();
386         return mWebStorageSizeManager;
387     }
388 
getAppCachePath()389     private String getAppCachePath() {
390         if (mAppCachePath == null) {
391             mAppCachePath = mContext.getDir("appcache", 0).getPath();
392         }
393         return mAppCachePath;
394     }
395 
updateSearchEngine(boolean force)396     private void updateSearchEngine(boolean force) {
397         String searchEngineName = getSearchEngineName();
398         if (force || mSearchEngine == null ||
399                 !mSearchEngine.getName().equals(searchEngineName)) {
400             mSearchEngine = SearchEngines.get(mContext, searchEngineName);
401          }
402     }
403 
getSearchEngine()404     public SearchEngine getSearchEngine() {
405         if (mSearchEngine == null) {
406             updateSearchEngine(false);
407         }
408         return mSearchEngine;
409     }
410 
isDebugEnabled()411     public boolean isDebugEnabled() {
412         requireInitialization();
413         return mPrefs.getBoolean(PREF_DEBUG_MENU, false);
414     }
415 
setDebugEnabled(boolean value)416     public void setDebugEnabled(boolean value) {
417         Editor edit = mPrefs.edit();
418         edit.putBoolean(PREF_DEBUG_MENU, value);
419         if (!value) {
420             // Reset to "safe" value
421             edit.putBoolean(PREF_ENABLE_HARDWARE_ACCEL_SKIA, false);
422         }
423         edit.apply();
424     }
425 
clearCache()426     public void clearCache() {
427         WebIconDatabase.getInstance().removeAllIcons();
428         if (mController != null) {
429             WebView current = mController.getCurrentWebView();
430             if (current != null) {
431                 current.clearCache(true);
432             }
433         }
434     }
435 
clearCookies()436     public void clearCookies() {
437         CookieManager.getInstance().removeAllCookie();
438     }
439 
clearHistory()440     public void clearHistory() {
441         ContentResolver resolver = mContext.getContentResolver();
442         Browser.clearHistory(resolver);
443         Browser.clearSearches(resolver);
444     }
445 
clearFormData()446     public void clearFormData() {
447         WebViewDatabase.getInstance(mContext).clearFormData();
448         if (mController!= null) {
449             WebView currentTopView = mController.getCurrentTopWebView();
450             if (currentTopView != null) {
451                 currentTopView.clearFormData();
452             }
453         }
454     }
455 
clearPasswords()456     public void clearPasswords() {
457         WebViewDatabase db = WebViewDatabase.getInstance(mContext);
458         db.clearUsernamePassword();
459         db.clearHttpAuthUsernamePassword();
460     }
461 
clearDatabases()462     public void clearDatabases() {
463         WebStorage.getInstance().deleteAllData();
464     }
465 
clearLocationAccess()466     public void clearLocationAccess() {
467         GeolocationPermissions.getInstance().clearAll();
468     }
469 
resetDefaultPreferences()470     public void resetDefaultPreferences() {
471         // Preserve autologin setting
472         long gal = mPrefs.getLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, -1);
473         mPrefs.edit()
474                 .clear()
475                 .putLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, gal)
476                 .apply();
477         resetCachedValues();
478         syncManagedSettings();
479     }
480 
resetCachedValues()481     private void resetCachedValues() {
482         updateSearchEngine(false);
483     }
484 
toggleDebugSettings()485     public void toggleDebugSettings() {
486         setDebugEnabled(!isDebugEnabled());
487     }
488 
hasDesktopUseragent(WebView view)489     public boolean hasDesktopUseragent(WebView view) {
490         return view != null && mCustomUserAgents.get(view.getSettings()) != null;
491     }
492 
toggleDesktopUseragent(WebView view)493     public void toggleDesktopUseragent(WebView view) {
494         if (view == null) {
495             return;
496         }
497         WebSettings settings = view.getSettings();
498         if (mCustomUserAgents.get(settings) != null) {
499             mCustomUserAgents.remove(settings);
500             settings.setUserAgentString(USER_AGENTS[getUserAgent()]);
501         } else {
502             mCustomUserAgents.put(settings, DESKTOP_USERAGENT);
503             settings.setUserAgentString(DESKTOP_USERAGENT);
504         }
505     }
506 
getAdjustedMinimumFontSize(int rawValue)507     public static int getAdjustedMinimumFontSize(int rawValue) {
508         rawValue++; // Preference starts at 0, min font at 1
509         if (rawValue > 1) {
510             rawValue += (MIN_FONT_SIZE_OFFSET - 2);
511         }
512         return rawValue;
513     }
514 
getAdjustedTextZoom(int rawValue)515     public int getAdjustedTextZoom(int rawValue) {
516         rawValue = (rawValue - TEXT_ZOOM_START_VAL) * TEXT_ZOOM_STEP;
517         return (int) ((rawValue + 100) * mFontSizeMult);
518     }
519 
getRawTextZoom(int percent)520     static int getRawTextZoom(int percent) {
521         return (percent - 100) / TEXT_ZOOM_STEP + TEXT_ZOOM_START_VAL;
522     }
523 
getAdjustedDoubleTapZoom(int rawValue)524     public int getAdjustedDoubleTapZoom(int rawValue) {
525         rawValue = (rawValue - DOUBLE_TAP_ZOOM_START_VAL) * DOUBLE_TAP_ZOOM_STEP;
526         return (int) ((rawValue + 100) * mFontSizeMult);
527     }
528 
getRawDoubleTapZoom(int percent)529     static int getRawDoubleTapZoom(int percent) {
530         return (percent - 100) / DOUBLE_TAP_ZOOM_STEP + DOUBLE_TAP_ZOOM_START_VAL;
531     }
532 
getPreferences()533     public SharedPreferences getPreferences() {
534         return mPrefs;
535     }
536 
537     // update connectivity-dependent options
updateConnectionType()538     public void updateConnectionType() {
539         ConnectivityManager cm = (ConnectivityManager)
540             mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
541         String linkPrefetchPreference = getLinkPrefetchEnabled();
542         boolean linkPrefetchAllowed = linkPrefetchPreference.
543             equals(getLinkPrefetchAlwaysPreferenceString(mContext));
544         NetworkInfo ni = cm.getActiveNetworkInfo();
545         if (ni != null) {
546             switch (ni.getType()) {
547                 case ConnectivityManager.TYPE_WIFI:
548                 case ConnectivityManager.TYPE_ETHERNET:
549                 case ConnectivityManager.TYPE_BLUETOOTH:
550                     linkPrefetchAllowed |= linkPrefetchPreference.
551                         equals(getLinkPrefetchOnWifiOnlyPreferenceString(mContext));
552                     break;
553                 case ConnectivityManager.TYPE_MOBILE:
554                 case ConnectivityManager.TYPE_MOBILE_DUN:
555                 case ConnectivityManager.TYPE_MOBILE_MMS:
556                 case ConnectivityManager.TYPE_MOBILE_SUPL:
557                 case ConnectivityManager.TYPE_WIMAX:
558                 default:
559                     break;
560             }
561         }
562         if (mLinkPrefetchAllowed != linkPrefetchAllowed) {
563             mLinkPrefetchAllowed = linkPrefetchAllowed;
564             syncManagedSettings();
565         }
566     }
567 
568     // -----------------------------
569     // getter/setters for accessibility_preferences.xml
570     // -----------------------------
571 
572     @Deprecated
getTextSize()573     private TextSize getTextSize() {
574         String textSize = mPrefs.getString(PREF_TEXT_SIZE, "NORMAL");
575         return TextSize.valueOf(textSize);
576     }
577 
getMinimumFontSize()578     public int getMinimumFontSize() {
579         int minFont = mPrefs.getInt(PREF_MIN_FONT_SIZE, 0);
580         return getAdjustedMinimumFontSize(minFont);
581     }
582 
forceEnableUserScalable()583     public boolean forceEnableUserScalable() {
584         return mPrefs.getBoolean(PREF_FORCE_USERSCALABLE, false);
585     }
586 
getTextZoom()587     public int getTextZoom() {
588         requireInitialization();
589         int textZoom = mPrefs.getInt(PREF_TEXT_ZOOM, 10);
590         return getAdjustedTextZoom(textZoom);
591     }
592 
setTextZoom(int percent)593     public void setTextZoom(int percent) {
594         mPrefs.edit().putInt(PREF_TEXT_ZOOM, getRawTextZoom(percent)).apply();
595     }
596 
getDoubleTapZoom()597     public int getDoubleTapZoom() {
598         requireInitialization();
599         int doubleTapZoom = mPrefs.getInt(PREF_DOUBLE_TAP_ZOOM, 5);
600         return getAdjustedDoubleTapZoom(doubleTapZoom);
601     }
602 
setDoubleTapZoom(int percent)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 
getSearchEngineName()611     public String getSearchEngineName() {
612         return mPrefs.getString(PREF_SEARCH_ENGINE, SearchEngine.GOOGLE);
613     }
614 
allowAppTabs()615     public boolean allowAppTabs() {
616         return mPrefs.getBoolean(PREF_ALLOW_APP_TABS, false);
617     }
618 
openInBackground()619     public boolean openInBackground() {
620         return mPrefs.getBoolean(PREF_OPEN_IN_BACKGROUND, false);
621     }
622 
enableJavascript()623     public boolean enableJavascript() {
624         return mPrefs.getBoolean(PREF_ENABLE_JAVASCRIPT, true);
625     }
626 
627     // TODO: Cache
getPluginState()628     public PluginState getPluginState() {
629         String state = mPrefs.getString(PREF_PLUGIN_STATE, "ON");
630         return PluginState.valueOf(state);
631     }
632 
633     // TODO: Cache
getDefaultZoom()634     public ZoomDensity getDefaultZoom() {
635         String zoom = mPrefs.getString(PREF_DEFAULT_ZOOM, "MEDIUM");
636         return ZoomDensity.valueOf(zoom);
637     }
638 
loadPageInOverviewMode()639     public boolean loadPageInOverviewMode() {
640         return mPrefs.getBoolean(PREF_LOAD_PAGE, true);
641     }
642 
autofitPages()643     public boolean autofitPages() {
644         return mPrefs.getBoolean(PREF_AUTOFIT_PAGES, true);
645     }
646 
blockPopupWindows()647     public boolean blockPopupWindows() {
648         return mPrefs.getBoolean(PREF_BLOCK_POPUP_WINDOWS, true);
649     }
650 
loadImages()651     public boolean loadImages() {
652         return mPrefs.getBoolean(PREF_LOAD_IMAGES, true);
653     }
654 
getDefaultTextEncoding()655     public String getDefaultTextEncoding() {
656         return mPrefs.getString(PREF_DEFAULT_TEXT_ENCODING, null);
657     }
658 
659     // -----------------------------
660     // getter/setters for general_preferences.xml
661     // -----------------------------
662 
getHomePage()663     public String getHomePage() {
664         return mPrefs.getString(PREF_HOMEPAGE, getFactoryResetHomeUrl(mContext));
665     }
666 
setHomePage(String value)667     public void setHomePage(String value) {
668         mPrefs.edit().putString(PREF_HOMEPAGE, value).apply();
669     }
670 
isAutofillEnabled()671     public boolean isAutofillEnabled() {
672         return mPrefs.getBoolean(PREF_AUTOFILL_ENABLED, true);
673     }
674 
setAutofillEnabled(boolean value)675     public void setAutofillEnabled(boolean value) {
676         mPrefs.edit().putBoolean(PREF_AUTOFILL_ENABLED, value).apply();
677     }
678 
679     // -----------------------------
680     // getter/setters for debug_preferences.xml
681     // -----------------------------
682 
isHardwareAccelerated()683     public boolean isHardwareAccelerated() {
684         if (!isDebugEnabled()) {
685             return true;
686         }
687         return mPrefs.getBoolean(PREF_ENABLE_HARDWARE_ACCEL, true);
688     }
689 
isSkiaHardwareAccelerated()690     public boolean isSkiaHardwareAccelerated() {
691         if (!isDebugEnabled()) {
692             return false;
693         }
694         return mPrefs.getBoolean(PREF_ENABLE_HARDWARE_ACCEL_SKIA, false);
695     }
696 
getUserAgent()697     public int getUserAgent() {
698         if (!isDebugEnabled()) {
699             return 0;
700         }
701         return Integer.parseInt(mPrefs.getString(PREF_USER_AGENT, "0"));
702     }
703 
704     // -----------------------------
705     // getter/setters for hidden_debug_preferences.xml
706     // -----------------------------
707 
enableVisualIndicator()708     public boolean enableVisualIndicator() {
709         if (!isDebugEnabled()) {
710             return false;
711         }
712         return mPrefs.getBoolean(PREF_ENABLE_VISUAL_INDICATOR, false);
713     }
714 
enableCpuUploadPath()715     public boolean enableCpuUploadPath() {
716         if (!isDebugEnabled()) {
717             return false;
718         }
719         return mPrefs.getBoolean(PREF_ENABLE_CPU_UPLOAD_PATH, false);
720     }
721 
enableJavascriptConsole()722     public boolean enableJavascriptConsole() {
723         if (!isDebugEnabled()) {
724             return false;
725         }
726         return mPrefs.getBoolean(PREF_JAVASCRIPT_CONSOLE, true);
727     }
728 
isWideViewport()729     public boolean isWideViewport() {
730         if (!isDebugEnabled()) {
731             return true;
732         }
733         return mPrefs.getBoolean(PREF_WIDE_VIEWPORT, true);
734     }
735 
isNormalLayout()736     public boolean isNormalLayout() {
737         if (!isDebugEnabled()) {
738             return false;
739         }
740         return mPrefs.getBoolean(PREF_NORMAL_LAYOUT, false);
741     }
742 
isTracing()743     public boolean isTracing() {
744         if (!isDebugEnabled()) {
745             return false;
746         }
747         return mPrefs.getBoolean(PREF_ENABLE_TRACING, false);
748     }
749 
enableLightTouch()750     public boolean enableLightTouch() {
751         if (!isDebugEnabled()) {
752             return false;
753         }
754         return mPrefs.getBoolean(PREF_ENABLE_LIGHT_TOUCH, false);
755     }
756 
enableNavDump()757     public boolean enableNavDump() {
758         if (!isDebugEnabled()) {
759             return false;
760         }
761         return mPrefs.getBoolean(PREF_ENABLE_NAV_DUMP, false);
762     }
763 
getJsEngineFlags()764     public String getJsEngineFlags() {
765         if (!isDebugEnabled()) {
766             return "";
767         }
768         return mPrefs.getString(PREF_JS_ENGINE_FLAGS, "");
769     }
770 
771     // -----------------------------
772     // getter/setters for lab_preferences.xml
773     // -----------------------------
774 
useQuickControls()775     public boolean useQuickControls() {
776         return mPrefs.getBoolean(PREF_ENABLE_QUICK_CONTROLS, false);
777     }
778 
useMostVisitedHomepage()779     public boolean useMostVisitedHomepage() {
780         return HomeProvider.MOST_VISITED.equals(getHomePage());
781     }
782 
useFullscreen()783     public boolean useFullscreen() {
784         return mPrefs.getBoolean(PREF_FULLSCREEN, false);
785     }
786 
useInvertedRendering()787     public boolean useInvertedRendering() {
788         return mPrefs.getBoolean(PREF_INVERTED, false);
789     }
790 
getInvertedContrast()791     public float getInvertedContrast() {
792         return 1 + (mPrefs.getInt(PREF_INVERTED_CONTRAST, 0) / 10f);
793     }
794 
795     // -----------------------------
796     // getter/setters for privacy_security_preferences.xml
797     // -----------------------------
798 
showSecurityWarnings()799     public boolean showSecurityWarnings() {
800         return mPrefs.getBoolean(PREF_SHOW_SECURITY_WARNINGS, true);
801     }
802 
acceptCookies()803     public boolean acceptCookies() {
804         return mPrefs.getBoolean(PREF_ACCEPT_COOKIES, true);
805     }
806 
saveFormdata()807     public boolean saveFormdata() {
808         return mPrefs.getBoolean(PREF_SAVE_FORMDATA, true);
809     }
810 
enableGeolocation()811     public boolean enableGeolocation() {
812         return mPrefs.getBoolean(PREF_ENABLE_GEOLOCATION, true);
813     }
814 
rememberPasswords()815     public boolean rememberPasswords() {
816         return mPrefs.getBoolean(PREF_REMEMBER_PASSWORDS, true);
817     }
818 
819     // -----------------------------
820     // getter/setters for bandwidth_preferences.xml
821     // -----------------------------
822 
getPreloadOnWifiOnlyPreferenceString(Context context)823     public static String getPreloadOnWifiOnlyPreferenceString(Context context) {
824         return context.getResources().getString(R.string.pref_data_preload_value_wifi_only);
825     }
826 
getPreloadAlwaysPreferenceString(Context context)827     public static String getPreloadAlwaysPreferenceString(Context context) {
828         return context.getResources().getString(R.string.pref_data_preload_value_always);
829     }
830 
831     private static final String DEAULT_PRELOAD_SECURE_SETTING_KEY =
832             "browser_default_preload_setting";
833 
getDefaultPreloadSetting()834     public String getDefaultPreloadSetting() {
835         String preload = Settings.Secure.getString(mContext.getContentResolver(),
836                 DEAULT_PRELOAD_SECURE_SETTING_KEY);
837         if (preload == null) {
838             preload = mContext.getResources().getString(R.string.pref_data_preload_default_value);
839         }
840         return preload;
841     }
842 
getPreloadEnabled()843     public String getPreloadEnabled() {
844         return mPrefs.getString(PREF_DATA_PRELOAD, getDefaultPreloadSetting());
845     }
846 
getLinkPrefetchOnWifiOnlyPreferenceString(Context context)847     public static String getLinkPrefetchOnWifiOnlyPreferenceString(Context context) {
848         return context.getResources().getString(R.string.pref_link_prefetch_value_wifi_only);
849     }
850 
getLinkPrefetchAlwaysPreferenceString(Context context)851     public static String getLinkPrefetchAlwaysPreferenceString(Context context) {
852         return context.getResources().getString(R.string.pref_link_prefetch_value_always);
853     }
854 
855     private static final String DEFAULT_LINK_PREFETCH_SECURE_SETTING_KEY =
856             "browser_default_link_prefetch_setting";
857 
getDefaultLinkPrefetchSetting()858     public String getDefaultLinkPrefetchSetting() {
859         String preload = Settings.Secure.getString(mContext.getContentResolver(),
860             DEFAULT_LINK_PREFETCH_SECURE_SETTING_KEY);
861         if (preload == null) {
862             preload = mContext.getResources().getString(R.string.pref_link_prefetch_default_value);
863         }
864         return preload;
865     }
866 
getLinkPrefetchEnabled()867     public String getLinkPrefetchEnabled() {
868         return mPrefs.getString(PREF_LINK_PREFETCH, getDefaultLinkPrefetchSetting());
869     }
870 
871     // -----------------------------
872     // getter/setters for browser recovery
873     // -----------------------------
874     /**
875      * The last time browser was started.
876      * @return The last browser start time as System.currentTimeMillis. This
877      * can be 0 if this is the first time or the last tab was closed.
878      */
getLastRecovered()879     public long getLastRecovered() {
880         return mPrefs.getLong(KEY_LAST_RECOVERED, 0);
881     }
882 
883     /**
884      * Sets the last browser start time.
885      * @param time The last time as System.currentTimeMillis that the browser
886      * was started. This should be set to 0 if the last tab is closed.
887      */
setLastRecovered(long time)888     public void setLastRecovered(long time) {
889         mPrefs.edit()
890             .putLong(KEY_LAST_RECOVERED, time)
891             .apply();
892     }
893 
894     /**
895      * Used to determine whether or not the previous browser run crashed. Once
896      * the previous state has been determined, the value will be set to false
897      * until a pause is received.
898      * @return true if the last browser run was paused or false if it crashed.
899      */
wasLastRunPaused()900     public boolean wasLastRunPaused() {
901         return mPrefs.getBoolean(KEY_LAST_RUN_PAUSED, false);
902     }
903 
904     /**
905      * Sets whether or not the last run was a pause or crash.
906      * @param isPaused Set to true When a pause is received or false after
907      * resuming.
908      */
setLastRunPaused(boolean isPaused)909     public void setLastRunPaused(boolean isPaused) {
910         mPrefs.edit()
911             .putBoolean(KEY_LAST_RUN_PAUSED, isPaused)
912             .apply();
913     }
914 }
915