Home | History | Annotate | Download | only in browser
      1 
      2 /*
      3  * Copyright (C) 2007 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.browser;
     19 
     20 import com.android.browser.search.SearchEngine;
     21 import com.android.browser.search.SearchEngines;
     22 
     23 import android.app.ActivityManager;
     24 import android.content.ComponentName;
     25 import android.content.ContentResolver;
     26 import android.content.Context;
     27 import android.content.pm.ActivityInfo;
     28 import android.content.SharedPreferences;
     29 import android.content.SharedPreferences.Editor;
     30 import android.database.ContentObserver;
     31 import android.os.Handler;
     32 import android.preference.PreferenceActivity;
     33 import android.preference.PreferenceScreen;
     34 import android.provider.Settings;
     35 import android.util.Log;
     36 import android.webkit.CookieManager;
     37 import android.webkit.GeolocationPermissions;
     38 import android.webkit.ValueCallback;
     39 import android.webkit.WebView;
     40 import android.webkit.WebViewDatabase;
     41 import android.webkit.WebIconDatabase;
     42 import android.webkit.WebSettings;
     43 import android.webkit.WebStorage;
     44 import android.preference.PreferenceManager;
     45 import android.provider.Browser;
     46 
     47 import java.util.HashMap;
     48 import java.util.Map;
     49 import java.util.Set;
     50 import java.util.Observable;
     51 
     52 /*
     53  * Package level class for storing various WebView and Browser settings. To use
     54  * this class:
     55  * BrowserSettings s = BrowserSettings.getInstance();
     56  * s.addObserver(webView.getSettings());
     57  * s.loadFromDb(context); // Only needed on app startup
     58  * s.javaScriptEnabled = true;
     59  * ... // set any other settings
     60  * s.update(); // this will update all the observers
     61  *
     62  * To remove an observer:
     63  * s.deleteObserver(webView.getSettings());
     64  */
     65 class BrowserSettings extends Observable {
     66 
     67     // Private variables for settings
     68     // NOTE: these defaults need to be kept in sync with the XML
     69     // until the performance of PreferenceManager.setDefaultValues()
     70     // is improved.
     71     // Note: boolean variables are set inside reset function.
     72     private boolean loadsImagesAutomatically;
     73     private boolean javaScriptEnabled;
     74     private WebSettings.PluginState pluginState;
     75     private boolean javaScriptCanOpenWindowsAutomatically;
     76     private boolean showSecurityWarnings;
     77     private boolean rememberPasswords;
     78     private boolean saveFormData;
     79     private boolean openInBackground;
     80     private String defaultTextEncodingName;
     81     private String homeUrl = "";
     82     private SearchEngine searchEngine;
     83     private boolean autoFitPage;
     84     private boolean landscapeOnly;
     85     private boolean loadsPageInOverviewMode;
     86     private boolean showDebugSettings;
     87     // HTML5 API flags
     88     private boolean appCacheEnabled;
     89     private boolean databaseEnabled;
     90     private boolean domStorageEnabled;
     91     private boolean geolocationEnabled;
     92     private boolean workersEnabled;  // only affects V8. JSC does not have a similar setting
     93     // HTML5 API configuration params
     94     private long appCacheMaxSize = Long.MAX_VALUE;
     95     private String appCachePath;  // default value set in loadFromDb().
     96     private String databasePath; // default value set in loadFromDb()
     97     private String geolocationDatabasePath; // default value set in loadFromDb()
     98     private WebStorageSizeManager webStorageSizeManager;
     99 
    100     private String jsFlags = "";
    101 
    102     private final static String TAG = "BrowserSettings";
    103 
    104     // Development settings
    105     public WebSettings.LayoutAlgorithm layoutAlgorithm =
    106         WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
    107     private boolean useWideViewPort = true;
    108     private int userAgent = 0;
    109     private boolean tracing = false;
    110     private boolean lightTouch = false;
    111     private boolean navDump = false;
    112 
    113     // By default the error console is shown once the user navigates to about:debug.
    114     // The setting can be then toggled from the settings menu.
    115     private boolean showConsole = true;
    116 
    117     // Private preconfigured values
    118     private static int minimumFontSize = 8;
    119     private static int minimumLogicalFontSize = 8;
    120     private static int defaultFontSize = 16;
    121     private static int defaultFixedFontSize = 13;
    122     private static WebSettings.TextSize textSize =
    123         WebSettings.TextSize.NORMAL;
    124     private static WebSettings.ZoomDensity zoomDensity =
    125         WebSettings.ZoomDensity.MEDIUM;
    126     private static int pageCacheCapacity;
    127 
    128     // Preference keys that are used outside this class
    129     public final static String PREF_CLEAR_CACHE = "privacy_clear_cache";
    130     public final static String PREF_CLEAR_COOKIES = "privacy_clear_cookies";
    131     public final static String PREF_CLEAR_HISTORY = "privacy_clear_history";
    132     public final static String PREF_HOMEPAGE = "homepage";
    133     public final static String PREF_SEARCH_ENGINE = "search_engine";
    134     public final static String PREF_CLEAR_FORM_DATA =
    135             "privacy_clear_form_data";
    136     public final static String PREF_CLEAR_PASSWORDS =
    137             "privacy_clear_passwords";
    138     public final static String PREF_EXTRAS_RESET_DEFAULTS =
    139             "reset_default_preferences";
    140     public final static String PREF_DEBUG_SETTINGS = "debug_menu";
    141     public final static String PREF_WEBSITE_SETTINGS = "website_settings";
    142     public final static String PREF_TEXT_SIZE = "text_size";
    143     public final static String PREF_DEFAULT_ZOOM = "default_zoom";
    144     public final static String PREF_DEFAULT_TEXT_ENCODING =
    145             "default_text_encoding";
    146     public final static String PREF_CLEAR_GEOLOCATION_ACCESS =
    147             "privacy_clear_geolocation_access";
    148 
    149     private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " +
    150             "U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.16 (KHTML, " +
    151             "like Gecko) Version/5.0 Safari/533.16";
    152 
    153     private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " +
    154             "CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 " +
    155             "(KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7";
    156 
    157     private static final String IPAD_USERAGENT = "Mozilla/5.0 (iPad; U; " +
    158             "CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 " +
    159             "(KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10";
    160 
    161     private static final String FROYO_USERAGENT = "Mozilla/5.0 (Linux; U; " +
    162             "Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 " +
    163             "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
    164 
    165     // Value to truncate strings when adding them to a TextView within
    166     // a ListView
    167     public final static int MAX_TEXTVIEW_LEN = 80;
    168 
    169     private TabControl mTabControl;
    170 
    171     // Single instance of the BrowserSettings for use in the Browser app.
    172     private static BrowserSettings sSingleton;
    173 
    174     // Private map of WebSettings to Observer objects used when deleting an
    175     // observer.
    176     private HashMap<WebSettings,Observer> mWebSettingsToObservers =
    177         new HashMap<WebSettings,Observer>();
    178 
    179     /*
    180      * An observer wrapper for updating a WebSettings object with the new
    181      * settings after a call to BrowserSettings.update().
    182      */
    183     static class Observer implements java.util.Observer {
    184         // Private WebSettings object that will be updated.
    185         private WebSettings mSettings;
    186 
    187         Observer(WebSettings w) {
    188             mSettings = w;
    189         }
    190 
    191         public void update(Observable o, Object arg) {
    192             BrowserSettings b = (BrowserSettings)o;
    193             WebSettings s = mSettings;
    194 
    195             s.setLayoutAlgorithm(b.layoutAlgorithm);
    196             if (b.userAgent == 0) {
    197                 // use the default ua string
    198                 s.setUserAgentString(null);
    199             } else if (b.userAgent == 1) {
    200                 s.setUserAgentString(DESKTOP_USERAGENT);
    201             } else if (b.userAgent == 2) {
    202                 s.setUserAgentString(IPHONE_USERAGENT);
    203             } else if (b.userAgent == 3) {
    204                 s.setUserAgentString(IPAD_USERAGENT);
    205             } else if (b.userAgent == 4) {
    206                 s.setUserAgentString(FROYO_USERAGENT);
    207             }
    208             s.setUseWideViewPort(b.useWideViewPort);
    209             s.setLoadsImagesAutomatically(b.loadsImagesAutomatically);
    210             s.setJavaScriptEnabled(b.javaScriptEnabled);
    211             s.setPluginState(b.pluginState);
    212             s.setJavaScriptCanOpenWindowsAutomatically(
    213                     b.javaScriptCanOpenWindowsAutomatically);
    214             s.setDefaultTextEncodingName(b.defaultTextEncodingName);
    215             s.setMinimumFontSize(b.minimumFontSize);
    216             s.setMinimumLogicalFontSize(b.minimumLogicalFontSize);
    217             s.setDefaultFontSize(b.defaultFontSize);
    218             s.setDefaultFixedFontSize(b.defaultFixedFontSize);
    219             s.setNavDump(b.navDump);
    220             s.setTextSize(b.textSize);
    221             s.setDefaultZoom(b.zoomDensity);
    222             s.setLightTouchEnabled(b.lightTouch);
    223             s.setSaveFormData(b.saveFormData);
    224             s.setSavePassword(b.rememberPasswords);
    225             s.setLoadWithOverviewMode(b.loadsPageInOverviewMode);
    226             s.setPageCacheCapacity(pageCacheCapacity);
    227 
    228             // WebView inside Browser doesn't want initial focus to be set.
    229             s.setNeedInitialFocus(false);
    230             // Browser supports multiple windows
    231             s.setSupportMultipleWindows(true);
    232 
    233             // HTML5 API flags
    234             s.setAppCacheEnabled(b.appCacheEnabled);
    235             s.setDatabaseEnabled(b.databaseEnabled);
    236             s.setDomStorageEnabled(b.domStorageEnabled);
    237             s.setWorkersEnabled(b.workersEnabled);  // This only affects V8.
    238             s.setGeolocationEnabled(b.geolocationEnabled);
    239 
    240             // HTML5 configuration parameters.
    241             s.setAppCacheMaxSize(b.appCacheMaxSize);
    242             s.setAppCachePath(b.appCachePath);
    243             s.setDatabasePath(b.databasePath);
    244             s.setGeolocationDatabasePath(b.geolocationDatabasePath);
    245 
    246             b.updateTabControlSettings();
    247         }
    248     }
    249 
    250     /**
    251      * Load settings from the browser app's database.
    252      * NOTE: Strings used for the preferences must match those specified
    253      * in the browser_preferences.xml
    254      * @param ctx A Context object used to query the browser's settings
    255      *            database. If the database exists, the saved settings will be
    256      *            stored in this BrowserSettings object. This will update all
    257      *            observers of this object.
    258      */
    259     public void loadFromDb(final Context ctx) {
    260         SharedPreferences p =
    261                 PreferenceManager.getDefaultSharedPreferences(ctx);
    262         // Set the default value for the Application Caches path.
    263         appCachePath = ctx.getDir("appcache", 0).getPath();
    264         // Determine the maximum size of the application cache.
    265         webStorageSizeManager = new WebStorageSizeManager(
    266                 ctx,
    267                 new WebStorageSizeManager.StatFsDiskInfo(appCachePath),
    268                 new WebStorageSizeManager.WebKitAppCacheInfo(appCachePath));
    269         appCacheMaxSize = webStorageSizeManager.getAppCacheMaxSize();
    270         // Set the default value for the Database path.
    271         databasePath = ctx.getDir("databases", 0).getPath();
    272         // Set the default value for the Geolocation database path.
    273         geolocationDatabasePath = ctx.getDir("geolocation", 0).getPath();
    274 
    275         if (p.getString(PREF_HOMEPAGE, "") == "") {
    276             // No home page preferences is set, set it to default.
    277             setHomePage(ctx, getFactoryResetHomeUrl(ctx));
    278         }
    279 
    280         // the cost of one cached page is ~3M (measured using nytimes.com). For
    281         // low end devices, we only cache one page. For high end devices, we try
    282         // to cache more pages, currently choose 5.
    283         ActivityManager am = (ActivityManager) ctx
    284                 .getSystemService(Context.ACTIVITY_SERVICE);
    285         if (am.getMemoryClass() > 16) {
    286             pageCacheCapacity = 5;
    287         } else {
    288             pageCacheCapacity = 1;
    289         }
    290 
    291     // Load the defaults from the xml
    292         // This call is TOO SLOW, need to manually keep the defaults
    293         // in sync
    294         //PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences);
    295         syncSharedPreferences(ctx, p);
    296     }
    297 
    298     /* package */ void syncSharedPreferences(Context ctx, SharedPreferences p) {
    299 
    300         homeUrl =
    301             p.getString(PREF_HOMEPAGE, homeUrl);
    302         String searchEngineName = p.getString(PREF_SEARCH_ENGINE,
    303                 SearchEngine.GOOGLE);
    304         if (searchEngine == null || !searchEngine.getName().equals(searchEngineName)) {
    305             if (searchEngine != null) {
    306                 if (searchEngine.supportsVoiceSearch()) {
    307                     // One or more tabs could have been in voice search mode.
    308                     // Clear it, since the new SearchEngine may not support
    309                     // it, or may handle it differently.
    310                     for (int i = 0; i < mTabControl.getTabCount(); i++) {
    311                         mTabControl.getTab(i).revertVoiceSearchMode();
    312                     }
    313                 }
    314                 searchEngine.close();
    315             }
    316             searchEngine = SearchEngines.get(ctx, searchEngineName);
    317         }
    318         Log.i(TAG, "Selected search engine: " + searchEngine);
    319 
    320         loadsImagesAutomatically = p.getBoolean("load_images",
    321                 loadsImagesAutomatically);
    322         javaScriptEnabled = p.getBoolean("enable_javascript",
    323                 javaScriptEnabled);
    324         pluginState = WebSettings.PluginState.valueOf(
    325                 p.getString("plugin_state", pluginState.name()));
    326         javaScriptCanOpenWindowsAutomatically = !p.getBoolean(
    327             "block_popup_windows",
    328             !javaScriptCanOpenWindowsAutomatically);
    329         showSecurityWarnings = p.getBoolean("show_security_warnings",
    330                 showSecurityWarnings);
    331         rememberPasswords = p.getBoolean("remember_passwords",
    332                 rememberPasswords);
    333         saveFormData = p.getBoolean("save_formdata",
    334                 saveFormData);
    335         boolean accept_cookies = p.getBoolean("accept_cookies",
    336                 CookieManager.getInstance().acceptCookie());
    337         CookieManager.getInstance().setAcceptCookie(accept_cookies);
    338         openInBackground = p.getBoolean("open_in_background", openInBackground);
    339         textSize = WebSettings.TextSize.valueOf(
    340                 p.getString(PREF_TEXT_SIZE, textSize.name()));
    341         zoomDensity = WebSettings.ZoomDensity.valueOf(
    342                 p.getString(PREF_DEFAULT_ZOOM, zoomDensity.name()));
    343         autoFitPage = p.getBoolean("autofit_pages", autoFitPage);
    344         loadsPageInOverviewMode = p.getBoolean("load_page",
    345                 loadsPageInOverviewMode);
    346         boolean landscapeOnlyTemp =
    347                 p.getBoolean("landscape_only", landscapeOnly);
    348         if (landscapeOnlyTemp != landscapeOnly) {
    349             landscapeOnly = landscapeOnlyTemp;
    350         }
    351         useWideViewPort = true; // use wide view port for either setting
    352         if (autoFitPage) {
    353             layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
    354         } else {
    355             layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL;
    356         }
    357         defaultTextEncodingName =
    358                 p.getString(PREF_DEFAULT_TEXT_ENCODING,
    359                         defaultTextEncodingName);
    360 
    361         showDebugSettings =
    362                 p.getBoolean(PREF_DEBUG_SETTINGS, showDebugSettings);
    363         // Debug menu items have precidence if the menu is visible
    364         if (showDebugSettings) {
    365             boolean small_screen = p.getBoolean("small_screen",
    366                     layoutAlgorithm ==
    367                     WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
    368             if (small_screen) {
    369                 layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN;
    370             } else {
    371                 boolean normal_layout = p.getBoolean("normal_layout",
    372                         layoutAlgorithm == WebSettings.LayoutAlgorithm.NORMAL);
    373                 if (normal_layout) {
    374                     layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL;
    375                 } else {
    376                     layoutAlgorithm =
    377                             WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
    378                 }
    379             }
    380             useWideViewPort = p.getBoolean("wide_viewport", useWideViewPort);
    381             tracing = p.getBoolean("enable_tracing", tracing);
    382             lightTouch = p.getBoolean("enable_light_touch", lightTouch);
    383             navDump = p.getBoolean("enable_nav_dump", navDump);
    384             userAgent = Integer.parseInt(p.getString("user_agent", "0"));
    385         }
    386         // JS flags is loaded from DB even if showDebugSettings is false,
    387         // so that it can be set once and be effective all the time.
    388         jsFlags = p.getString("js_engine_flags", "");
    389 
    390         // Read the setting for showing/hiding the JS Console always so that should the
    391         // user enable debug settings, we already know if we should show the console.
    392         // The user will never see the console unless they navigate to about:debug,
    393         // regardless of the setting we read here. This setting is only used after debug
    394         // is enabled.
    395         showConsole = p.getBoolean("javascript_console", showConsole);
    396 
    397         // HTML5 API flags
    398         appCacheEnabled = p.getBoolean("enable_appcache", appCacheEnabled);
    399         databaseEnabled = p.getBoolean("enable_database", databaseEnabled);
    400         domStorageEnabled = p.getBoolean("enable_domstorage", domStorageEnabled);
    401         geolocationEnabled = p.getBoolean("enable_geolocation", geolocationEnabled);
    402         workersEnabled = p.getBoolean("enable_workers", workersEnabled);
    403 
    404         update();
    405     }
    406 
    407     public String getHomePage() {
    408         return homeUrl;
    409     }
    410 
    411     public SearchEngine getSearchEngine() {
    412         return searchEngine;
    413     }
    414 
    415     public String getJsFlags() {
    416         return jsFlags;
    417     }
    418 
    419     public WebStorageSizeManager getWebStorageSizeManager() {
    420         return webStorageSizeManager;
    421     }
    422 
    423     public void setHomePage(Context context, String url) {
    424         Editor ed = PreferenceManager.
    425                 getDefaultSharedPreferences(context).edit();
    426         ed.putString(PREF_HOMEPAGE, url);
    427         ed.apply();
    428         homeUrl = url;
    429     }
    430 
    431     public WebSettings.TextSize getTextSize() {
    432         return textSize;
    433     }
    434 
    435     public WebSettings.ZoomDensity getDefaultZoom() {
    436         return zoomDensity;
    437     }
    438 
    439     public boolean openInBackground() {
    440         return openInBackground;
    441     }
    442 
    443     public boolean showSecurityWarnings() {
    444         return showSecurityWarnings;
    445     }
    446 
    447     public boolean isTracing() {
    448         return tracing;
    449     }
    450 
    451     public boolean isLightTouch() {
    452         return lightTouch;
    453     }
    454 
    455     public boolean isNavDump() {
    456         return navDump;
    457     }
    458 
    459     public boolean showDebugSettings() {
    460         return showDebugSettings;
    461     }
    462 
    463     public void toggleDebugSettings() {
    464         showDebugSettings = !showDebugSettings;
    465         navDump = showDebugSettings;
    466         update();
    467     }
    468 
    469     /**
    470      * Add a WebSettings object to the list of observers that will be updated
    471      * when update() is called.
    472      *
    473      * @param s A WebSettings object that is strictly tied to the life of a
    474      *            WebView.
    475      */
    476     public Observer addObserver(WebSettings s) {
    477         Observer old = mWebSettingsToObservers.get(s);
    478         if (old != null) {
    479             super.deleteObserver(old);
    480         }
    481         Observer o = new Observer(s);
    482         mWebSettingsToObservers.put(s, o);
    483         super.addObserver(o);
    484         return o;
    485     }
    486 
    487     /**
    488      * Delete the given WebSettings observer from the list of observers.
    489      * @param s The WebSettings object to be deleted.
    490      */
    491     public void deleteObserver(WebSettings s) {
    492         Observer o = mWebSettingsToObservers.get(s);
    493         if (o != null) {
    494             mWebSettingsToObservers.remove(s);
    495             super.deleteObserver(o);
    496         }
    497     }
    498 
    499     /*
    500      * Package level method for obtaining a single app instance of the
    501      * BrowserSettings.
    502      */
    503     /*package*/ static BrowserSettings getInstance() {
    504         if (sSingleton == null ) {
    505             sSingleton = new BrowserSettings();
    506         }
    507         return sSingleton;
    508     }
    509 
    510     /*
    511      * Package level method for associating the BrowserSettings with TabControl
    512      */
    513     /* package */void setTabControl(TabControl tabControl) {
    514         mTabControl = tabControl;
    515         updateTabControlSettings();
    516     }
    517 
    518     /*
    519      * Update all the observers of the object.
    520      */
    521     /*package*/ void update() {
    522         setChanged();
    523         notifyObservers();
    524     }
    525 
    526     /*package*/ void clearCache(Context context) {
    527         WebIconDatabase.getInstance().removeAllIcons();
    528         if (mTabControl != null) {
    529             WebView current = mTabControl.getCurrentWebView();
    530             if (current != null) {
    531                 current.clearCache(true);
    532             }
    533         }
    534     }
    535 
    536     /*package*/ void clearCookies(Context context) {
    537         CookieManager.getInstance().removeAllCookie();
    538     }
    539 
    540     /* package */void clearHistory(Context context) {
    541         ContentResolver resolver = context.getContentResolver();
    542         Browser.clearHistory(resolver);
    543         Browser.clearSearches(resolver);
    544     }
    545 
    546     /* package */ void clearFormData(Context context) {
    547         WebViewDatabase.getInstance(context).clearFormData();
    548         if (mTabControl != null) {
    549             WebView currentTopView = mTabControl.getCurrentTopWebView();
    550             if (currentTopView != null) {
    551                 currentTopView.clearFormData();
    552             }
    553         }
    554     }
    555 
    556     /*package*/ void clearPasswords(Context context) {
    557         WebViewDatabase db = WebViewDatabase.getInstance(context);
    558         db.clearUsernamePassword();
    559         db.clearHttpAuthUsernamePassword();
    560     }
    561 
    562     private void updateTabControlSettings() {
    563         // Enable/disable the error console.
    564         mTabControl.getBrowserActivity().setShouldShowErrorConsole(
    565             showDebugSettings && showConsole);
    566         mTabControl.getBrowserActivity().setRequestedOrientation(
    567             landscapeOnly ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
    568             : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    569     }
    570 
    571     private void maybeDisableWebsiteSettings(Context context) {
    572         PreferenceActivity activity = (PreferenceActivity) context;
    573         final PreferenceScreen screen = (PreferenceScreen)
    574             activity.findPreference(BrowserSettings.PREF_WEBSITE_SETTINGS);
    575         screen.setEnabled(false);
    576         WebStorage.getInstance().getOrigins(new ValueCallback<Map>() {
    577             public void onReceiveValue(Map webStorageOrigins) {
    578                 if ((webStorageOrigins != null) && !webStorageOrigins.isEmpty()) {
    579                     screen.setEnabled(true);
    580                 }
    581             }
    582         });
    583 
    584         GeolocationPermissions.getInstance().getOrigins(new ValueCallback<Set<String> >() {
    585             public void onReceiveValue(Set<String> geolocationOrigins) {
    586                 if ((geolocationOrigins != null) && !geolocationOrigins.isEmpty()) {
    587                     screen.setEnabled(true);
    588                 }
    589             }
    590         });
    591     }
    592 
    593     /*package*/ void clearDatabases(Context context) {
    594         WebStorage.getInstance().deleteAllData();
    595         maybeDisableWebsiteSettings(context);
    596     }
    597 
    598     /*package*/ void clearLocationAccess(Context context) {
    599         GeolocationPermissions.getInstance().clearAll();
    600         maybeDisableWebsiteSettings(context);
    601     }
    602 
    603     /*package*/ void resetDefaultPreferences(Context ctx) {
    604         reset();
    605         SharedPreferences p =
    606             PreferenceManager.getDefaultSharedPreferences(ctx);
    607         p.edit().clear().apply();
    608         PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences,
    609                 true);
    610         // reset homeUrl
    611         setHomePage(ctx, getFactoryResetHomeUrl(ctx));
    612         // reset appcache max size
    613         appCacheMaxSize = webStorageSizeManager.getAppCacheMaxSize();
    614     }
    615 
    616     private String getFactoryResetHomeUrl(Context context) {
    617         String url = context.getResources().getString(R.string.homepage_base);
    618         if (url.indexOf("{CID}") != -1) {
    619             url = url.replace("{CID}",
    620                     BrowserProvider.getClientId(context.getContentResolver()));
    621         }
    622         return url;
    623     }
    624 
    625     // Private constructor that does nothing.
    626     private BrowserSettings() {
    627         reset();
    628     }
    629 
    630     private void reset() {
    631         // Private variables for settings
    632         // NOTE: these defaults need to be kept in sync with the XML
    633         // until the performance of PreferenceManager.setDefaultValues()
    634         // is improved.
    635         loadsImagesAutomatically = true;
    636         javaScriptEnabled = true;
    637         pluginState = WebSettings.PluginState.ON;
    638         javaScriptCanOpenWindowsAutomatically = false;
    639         showSecurityWarnings = true;
    640         rememberPasswords = true;
    641         saveFormData = true;
    642         openInBackground = false;
    643         autoFitPage = true;
    644         landscapeOnly = false;
    645         loadsPageInOverviewMode = true;
    646         showDebugSettings = false;
    647         // HTML5 API flags
    648         appCacheEnabled = true;
    649         databaseEnabled = true;
    650         domStorageEnabled = true;
    651         geolocationEnabled = true;
    652         workersEnabled = true;  // only affects V8. JSC does not have a similar setting
    653     }
    654 }
    655