blob: bb5c4bb2668cb7923ac69ae4f7eda9303baf4c3b [file] [log] [blame]
Cary Clarkf2407c62009-09-04 12:25:10 -04001
The Android Open Source Project0c908882009-03-03 19:32:16 -08002/*
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
18package com.android.browser;
19
Bjorn Bringertd2670652010-09-13 14:06:41 +010020import com.android.browser.search.SearchEngine;
21import com.android.browser.search.SearchEngines;
22
Grace Kloba9804c432009-12-02 11:07:40 -080023import android.app.ActivityManager;
Bjorn Bringertd2670652010-09-13 14:06:41 +010024import android.content.ComponentName;
The Android Open Source Project0c908882009-03-03 19:32:16 -080025import android.content.ContentResolver;
Ed Tam8ba13bc2011-05-05 16:19:48 -070026import android.content.ContentUris;
27import android.content.ContentValues;
The Android Open Source Project0c908882009-03-03 19:32:16 -080028import android.content.Context;
29import android.content.pm.ActivityInfo;
Ed Tam8ba13bc2011-05-05 16:19:48 -070030import android.content.pm.PackageManager;
The Android Open Source Project0c908882009-03-03 19:32:16 -080031import android.content.SharedPreferences;
32import android.content.SharedPreferences.Editor;
Bjorn Bringertd2670652010-09-13 14:06:41 +010033import android.database.ContentObserver;
Ed Tam8ba13bc2011-05-05 16:19:48 -070034import android.database.Cursor;
35import android.net.Uri;
36import android.os.AsyncTask;
Bjorn Bringertd2670652010-09-13 14:06:41 +010037import android.os.Handler;
Nicolas Roard78a98e42009-05-11 13:34:17 +010038import android.preference.PreferenceActivity;
39import android.preference.PreferenceScreen;
Ed Tam8ba13bc2011-05-05 16:19:48 -070040import android.provider.Browser.BookmarkColumns;
Bjorn Bringertd2670652010-09-13 14:06:41 +010041import android.provider.Settings;
42import android.util.Log;
The Android Open Source Project0c908882009-03-03 19:32:16 -080043import android.webkit.CookieManager;
Steve Blockf344d032009-07-30 10:50:45 +010044import android.webkit.GeolocationPermissions;
Nicolas Roard99b3ae12009-09-22 15:17:52 +010045import android.webkit.ValueCallback;
The Android Open Source Project0c908882009-03-03 19:32:16 -080046import android.webkit.WebView;
47import android.webkit.WebViewDatabase;
48import android.webkit.WebIconDatabase;
49import android.webkit.WebSettings;
Nicolas Roard78a98e42009-05-11 13:34:17 +010050import android.webkit.WebStorage;
The Android Open Source Project0c908882009-03-03 19:32:16 -080051import android.preference.PreferenceManager;
52import android.provider.Browser;
53
54import java.util.HashMap;
Nicolas Roard99b3ae12009-09-22 15:17:52 +010055import java.util.Map;
56import java.util.Set;
The Android Open Source Project0c908882009-03-03 19:32:16 -080057import java.util.Observable;
58
59/*
60 * Package level class for storing various WebView and Browser settings. To use
61 * this class:
62 * BrowserSettings s = BrowserSettings.getInstance();
63 * s.addObserver(webView.getSettings());
64 * s.loadFromDb(context); // Only needed on app startup
65 * s.javaScriptEnabled = true;
66 * ... // set any other settings
67 * s.update(); // this will update all the observers
68 *
69 * To remove an observer:
70 * s.deleteObserver(webView.getSettings());
71 */
72class BrowserSettings extends Observable {
73
Leon Scroggins9ac587d2009-04-20 12:53:46 -040074 // Private variables for settings
The Android Open Source Project0c908882009-03-03 19:32:16 -080075 // NOTE: these defaults need to be kept in sync with the XML
76 // until the performance of PreferenceManager.setDefaultValues()
77 // is improved.
Shimeng (Simon) Wangf7392712010-03-10 16:44:31 -080078 // Note: boolean variables are set inside reset function.
79 private boolean loadsImagesAutomatically;
80 private boolean javaScriptEnabled;
Patrick Scotte536b332010-03-22 10:19:32 -040081 private WebSettings.PluginState pluginState;
Shimeng (Simon) Wangf7392712010-03-10 16:44:31 -080082 private boolean javaScriptCanOpenWindowsAutomatically;
83 private boolean showSecurityWarnings;
84 private boolean rememberPasswords;
85 private boolean saveFormData;
86 private boolean openInBackground;
The Android Open Source Project0c908882009-03-03 19:32:16 -080087 private String defaultTextEncodingName;
Grace Klobaf2c5c1b2009-05-26 10:48:31 -070088 private String homeUrl = "";
Bjorn Bringertd2670652010-09-13 14:06:41 +010089 private SearchEngine searchEngine;
Shimeng (Simon) Wangf7392712010-03-10 16:44:31 -080090 private boolean autoFitPage;
91 private boolean landscapeOnly;
92 private boolean loadsPageInOverviewMode;
93 private boolean showDebugSettings;
Andrei Popescu01068702009-08-03 16:03:24 +010094 // HTML5 API flags
Shimeng (Simon) Wangf7392712010-03-10 16:44:31 -080095 private boolean appCacheEnabled;
96 private boolean databaseEnabled;
97 private boolean domStorageEnabled;
98 private boolean geolocationEnabled;
99 private boolean workersEnabled; // only affects V8. JSC does not have a similar setting
Andrei Popescu01068702009-08-03 16:03:24 +0100100 // HTML5 API configuration params
101 private long appCacheMaxSize = Long.MAX_VALUE;
102 private String appCachePath; // default value set in loadFromDb().
103 private String databasePath; // default value set in loadFromDb()
Steve Block5029cf02009-08-21 13:16:58 +0100104 private String geolocationDatabasePath; // default value set in loadFromDb()
Andrei Popescu01068702009-08-03 16:03:24 +0100105 private WebStorageSizeManager webStorageSizeManager;
106
107 private String jsFlags = "";
The Android Open Source Project0c908882009-03-03 19:32:16 -0800108
Nicolas Roard78a98e42009-05-11 13:34:17 +0100109 private final static String TAG = "BrowserSettings";
110
The Android Open Source Project0c908882009-03-03 19:32:16 -0800111 // Development settings
112 public WebSettings.LayoutAlgorithm layoutAlgorithm =
113 WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
114 private boolean useWideViewPort = true;
115 private int userAgent = 0;
116 private boolean tracing = false;
117 private boolean lightTouch = false;
118 private boolean navDump = false;
Feng Qianb3c02da2009-06-29 15:58:08 -0700119
Ben Murdochbff2d602009-07-01 20:19:05 +0100120 // By default the error console is shown once the user navigates to about:debug.
121 // The setting can be then toggled from the settings menu.
122 private boolean showConsole = true;
123
The Android Open Source Project0c908882009-03-03 19:32:16 -0800124 // Private preconfigured values
125 private static int minimumFontSize = 8;
126 private static int minimumLogicalFontSize = 8;
127 private static int defaultFontSize = 16;
128 private static int defaultFixedFontSize = 13;
129 private static WebSettings.TextSize textSize =
130 WebSettings.TextSize.NORMAL;
Grace Kloba2f830682009-06-25 11:08:53 -0700131 private static WebSettings.ZoomDensity zoomDensity =
132 WebSettings.ZoomDensity.MEDIUM;
Grace Kloba9804c432009-12-02 11:07:40 -0800133 private static int pageCacheCapacity;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800134
135 // Preference keys that are used outside this class
136 public final static String PREF_CLEAR_CACHE = "privacy_clear_cache";
137 public final static String PREF_CLEAR_COOKIES = "privacy_clear_cookies";
138 public final static String PREF_CLEAR_HISTORY = "privacy_clear_history";
139 public final static String PREF_HOMEPAGE = "homepage";
Bjorn Bringertd2670652010-09-13 14:06:41 +0100140 public final static String PREF_SEARCH_ENGINE = "search_engine";
The Android Open Source Project0c908882009-03-03 19:32:16 -0800141 public final static String PREF_CLEAR_FORM_DATA =
142 "privacy_clear_form_data";
143 public final static String PREF_CLEAR_PASSWORDS =
144 "privacy_clear_passwords";
145 public final static String PREF_EXTRAS_RESET_DEFAULTS =
146 "reset_default_preferences";
147 public final static String PREF_DEBUG_SETTINGS = "debug_menu";
Nicolas Roarde46990e2009-06-19 16:27:49 +0100148 public final static String PREF_WEBSITE_SETTINGS = "website_settings";
The Android Open Source Project0c908882009-03-03 19:32:16 -0800149 public final static String PREF_TEXT_SIZE = "text_size";
Grace Kloba2f830682009-06-25 11:08:53 -0700150 public final static String PREF_DEFAULT_ZOOM = "default_zoom";
The Android Open Source Project0c908882009-03-03 19:32:16 -0800151 public final static String PREF_DEFAULT_TEXT_ENCODING =
152 "default_text_encoding";
Steve Blockc6f577f2009-08-20 18:11:08 +0100153 public final static String PREF_CLEAR_GEOLOCATION_ACCESS =
154 "privacy_clear_geolocation_access";
The Android Open Source Project0c908882009-03-03 19:32:16 -0800155
156 private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " +
Bart Searsf6915fb2010-07-08 19:58:22 -0700157 "U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.16 (KHTML, " +
158 "like Gecko) Version/5.0 Safari/533.16";
The Android Open Source Project0c908882009-03-03 19:32:16 -0800159
160 private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " +
Bart Searsf6915fb2010-07-08 19:58:22 -0700161 "CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 " +
162 "(KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7";
163
164 private static final String IPAD_USERAGENT = "Mozilla/5.0 (iPad; U; " +
165 "CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 " +
166 "(KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10";
167
168 private static final String FROYO_USERAGENT = "Mozilla/5.0 (Linux; U; " +
169 "Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 " +
170 "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
The Android Open Source Project0c908882009-03-03 19:32:16 -0800171
172 // Value to truncate strings when adding them to a TextView within
173 // a ListView
174 public final static int MAX_TEXTVIEW_LEN = 80;
175
Ed Tam8ba13bc2011-05-05 16:19:48 -0700176 public static final String RLZ_PROVIDER = "com.google.android.partnersetup.rlzappprovider";
177 public static final Uri RLZ_PROVIDER_URI = Uri.parse("content://" + RLZ_PROVIDER + "/");
178
179 private String mRlzValue = "";
180
The Android Open Source Project0c908882009-03-03 19:32:16 -0800181 private TabControl mTabControl;
182
183 // Single instance of the BrowserSettings for use in the Browser app.
184 private static BrowserSettings sSingleton;
185
186 // Private map of WebSettings to Observer objects used when deleting an
187 // observer.
188 private HashMap<WebSettings,Observer> mWebSettingsToObservers =
189 new HashMap<WebSettings,Observer>();
190
191 /*
192 * An observer wrapper for updating a WebSettings object with the new
193 * settings after a call to BrowserSettings.update().
194 */
195 static class Observer implements java.util.Observer {
196 // Private WebSettings object that will be updated.
197 private WebSettings mSettings;
198
199 Observer(WebSettings w) {
200 mSettings = w;
201 }
202
203 public void update(Observable o, Object arg) {
204 BrowserSettings b = (BrowserSettings)o;
205 WebSettings s = mSettings;
206
207 s.setLayoutAlgorithm(b.layoutAlgorithm);
208 if (b.userAgent == 0) {
209 // use the default ua string
210 s.setUserAgentString(null);
211 } else if (b.userAgent == 1) {
212 s.setUserAgentString(DESKTOP_USERAGENT);
213 } else if (b.userAgent == 2) {
214 s.setUserAgentString(IPHONE_USERAGENT);
Bart Searsf6915fb2010-07-08 19:58:22 -0700215 } else if (b.userAgent == 3) {
216 s.setUserAgentString(IPAD_USERAGENT);
217 } else if (b.userAgent == 4) {
218 s.setUserAgentString(FROYO_USERAGENT);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800219 }
220 s.setUseWideViewPort(b.useWideViewPort);
221 s.setLoadsImagesAutomatically(b.loadsImagesAutomatically);
222 s.setJavaScriptEnabled(b.javaScriptEnabled);
Patrick Scotte536b332010-03-22 10:19:32 -0400223 s.setPluginState(b.pluginState);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800224 s.setJavaScriptCanOpenWindowsAutomatically(
225 b.javaScriptCanOpenWindowsAutomatically);
226 s.setDefaultTextEncodingName(b.defaultTextEncodingName);
227 s.setMinimumFontSize(b.minimumFontSize);
228 s.setMinimumLogicalFontSize(b.minimumLogicalFontSize);
229 s.setDefaultFontSize(b.defaultFontSize);
230 s.setDefaultFixedFontSize(b.defaultFixedFontSize);
231 s.setNavDump(b.navDump);
232 s.setTextSize(b.textSize);
Grace Kloba2f830682009-06-25 11:08:53 -0700233 s.setDefaultZoom(b.zoomDensity);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800234 s.setLightTouchEnabled(b.lightTouch);
235 s.setSaveFormData(b.saveFormData);
236 s.setSavePassword(b.rememberPasswords);
Grace Kloba5b4b8f12009-08-05 17:19:17 -0700237 s.setLoadWithOverviewMode(b.loadsPageInOverviewMode);
Grace Kloba79565032009-11-24 14:23:39 -0800238 s.setPageCacheCapacity(pageCacheCapacity);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800239
240 // WebView inside Browser doesn't want initial focus to be set.
241 s.setNeedInitialFocus(false);
242 // Browser supports multiple windows
243 s.setSupportMultipleWindows(true);
Huahui Wu604a5982011-03-22 15:00:11 -0700244 // disable content url access
245 s.setAllowContentAccess(false);
Ben Murdoch092dd5d2009-04-22 12:34:12 +0100246
Andrei Popescu01068702009-08-03 16:03:24 +0100247 // HTML5 API flags
248 s.setAppCacheEnabled(b.appCacheEnabled);
Ben Murdoch092dd5d2009-04-22 12:34:12 +0100249 s.setDatabaseEnabled(b.databaseEnabled);
Ben Murdoch734a0662009-06-02 19:11:52 +0100250 s.setDomStorageEnabled(b.domStorageEnabled);
Andrei Popescu01068702009-08-03 16:03:24 +0100251 s.setWorkersEnabled(b.workersEnabled); // This only affects V8.
Steve Block97b08022009-08-21 10:26:25 +0100252 s.setGeolocationEnabled(b.geolocationEnabled);
Ben Murdoch092dd5d2009-04-22 12:34:12 +0100253
Andrei Popescu01068702009-08-03 16:03:24 +0100254 // HTML5 configuration parameters.
Andrei Popescu20634ce2009-07-22 16:46:55 +0100255 s.setAppCacheMaxSize(b.appCacheMaxSize);
Andrei Popescu01068702009-08-03 16:03:24 +0100256 s.setAppCachePath(b.appCachePath);
257 s.setDatabasePath(b.databasePath);
Steve Block5029cf02009-08-21 13:16:58 +0100258 s.setGeolocationDatabasePath(b.geolocationDatabasePath);
Ben Murdochbff2d602009-07-01 20:19:05 +0100259
Shimeng (Simon) Wang161974f2010-03-09 14:30:07 -0800260 b.updateTabControlSettings();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800261 }
262 }
263
264 /**
265 * Load settings from the browser app's database.
266 * NOTE: Strings used for the preferences must match those specified
267 * in the browser_preferences.xml
268 * @param ctx A Context object used to query the browser's settings
269 * database. If the database exists, the saved settings will be
270 * stored in this BrowserSettings object. This will update all
271 * observers of this object.
272 */
Bjorn Bringertd2670652010-09-13 14:06:41 +0100273 public void loadFromDb(final Context ctx) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800274 SharedPreferences p =
275 PreferenceManager.getDefaultSharedPreferences(ctx);
Andrei Popescu5151ac12009-04-17 10:43:07 +0100276 // Set the default value for the Application Caches path.
277 appCachePath = ctx.getDir("appcache", 0).getPath();
Andrei Popescu20634ce2009-07-22 16:46:55 +0100278 // Determine the maximum size of the application cache.
Andrei Popescu907c5762009-07-29 14:44:24 +0100279 webStorageSizeManager = new WebStorageSizeManager(
280 ctx,
281 new WebStorageSizeManager.StatFsDiskInfo(appCachePath),
282 new WebStorageSizeManager.WebKitAppCacheInfo(appCachePath));
Andrei Popescu79e82b72009-07-27 12:01:59 +0100283 appCacheMaxSize = webStorageSizeManager.getAppCacheMaxSize();
Ben Murdoch092dd5d2009-04-22 12:34:12 +0100284 // Set the default value for the Database path.
285 databasePath = ctx.getDir("databases", 0).getPath();
Steve Block5029cf02009-08-21 13:16:58 +0100286 // Set the default value for the Geolocation database path.
287 geolocationDatabasePath = ctx.getDir("geolocation", 0).getPath();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800288
Shimeng (Simon) Wange83e9062010-03-29 16:13:09 -0700289 if (p.getString(PREF_HOMEPAGE, "") == "") {
290 // No home page preferences is set, set it to default.
291 setHomePage(ctx, getFactoryResetHomeUrl(ctx));
292 }
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -0700293
Grace Kloba9804c432009-12-02 11:07:40 -0800294 // the cost of one cached page is ~3M (measured using nytimes.com). For
295 // low end devices, we only cache one page. For high end devices, we try
296 // to cache more pages, currently choose 5.
297 ActivityManager am = (ActivityManager) ctx
298 .getSystemService(Context.ACTIVITY_SERVICE);
299 if (am.getMemoryClass() > 16) {
Andrei Popescuba676ef2010-03-29 12:12:55 +0100300 pageCacheCapacity = 5;
Grace Kloba9804c432009-12-02 11:07:40 -0800301 } else {
302 pageCacheCapacity = 1;
303 }
304
Bjorn Bringertd2670652010-09-13 14:06:41 +0100305 // Load the defaults from the xml
The Android Open Source Project0c908882009-03-03 19:32:16 -0800306 // This call is TOO SLOW, need to manually keep the defaults
307 // in sync
308 //PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences);
Bjorn Bringertd2670652010-09-13 14:06:41 +0100309 syncSharedPreferences(ctx, p);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800310 }
311
Bjorn Bringertd2670652010-09-13 14:06:41 +0100312 /* package */ void syncSharedPreferences(Context ctx, SharedPreferences p) {
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -0700313
The Android Open Source Project0c908882009-03-03 19:32:16 -0800314 homeUrl =
315 p.getString(PREF_HOMEPAGE, homeUrl);
Leon Scroggins III31306602010-09-17 11:10:29 -0400316 String searchEngineName = p.getString(PREF_SEARCH_ENGINE,
317 SearchEngine.GOOGLE);
Bjorn Bringertd2670652010-09-13 14:06:41 +0100318 if (searchEngine == null || !searchEngine.getName().equals(searchEngineName)) {
319 if (searchEngine != null) {
Leon Scroggins III95d9bfd2010-09-14 14:02:36 -0400320 if (searchEngine.supportsVoiceSearch()) {
321 // One or more tabs could have been in voice search mode.
322 // Clear it, since the new SearchEngine may not support
323 // it, or may handle it differently.
324 for (int i = 0; i < mTabControl.getTabCount(); i++) {
325 mTabControl.getTab(i).revertVoiceSearchMode();
326 }
327 }
Bjorn Bringertd2670652010-09-13 14:06:41 +0100328 searchEngine.close();
329 }
330 searchEngine = SearchEngines.get(ctx, searchEngineName);
331 }
332 Log.i(TAG, "Selected search engine: " + searchEngine);
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -0700333
The Android Open Source Project0c908882009-03-03 19:32:16 -0800334 loadsImagesAutomatically = p.getBoolean("load_images",
335 loadsImagesAutomatically);
336 javaScriptEnabled = p.getBoolean("enable_javascript",
337 javaScriptEnabled);
Patrick Scotte536b332010-03-22 10:19:32 -0400338 pluginState = WebSettings.PluginState.valueOf(
339 p.getString("plugin_state", pluginState.name()));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800340 javaScriptCanOpenWindowsAutomatically = !p.getBoolean(
341 "block_popup_windows",
342 !javaScriptCanOpenWindowsAutomatically);
343 showSecurityWarnings = p.getBoolean("show_security_warnings",
344 showSecurityWarnings);
345 rememberPasswords = p.getBoolean("remember_passwords",
346 rememberPasswords);
347 saveFormData = p.getBoolean("save_formdata",
348 saveFormData);
349 boolean accept_cookies = p.getBoolean("accept_cookies",
350 CookieManager.getInstance().acceptCookie());
351 CookieManager.getInstance().setAcceptCookie(accept_cookies);
352 openInBackground = p.getBoolean("open_in_background", openInBackground);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800353 textSize = WebSettings.TextSize.valueOf(
354 p.getString(PREF_TEXT_SIZE, textSize.name()));
Grace Kloba2f830682009-06-25 11:08:53 -0700355 zoomDensity = WebSettings.ZoomDensity.valueOf(
356 p.getString(PREF_DEFAULT_ZOOM, zoomDensity.name()));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800357 autoFitPage = p.getBoolean("autofit_pages", autoFitPage);
Grace Kloba5b4b8f12009-08-05 17:19:17 -0700358 loadsPageInOverviewMode = p.getBoolean("load_page",
359 loadsPageInOverviewMode);
Leon Scrogginsb0cd0722009-03-31 14:31:22 -0700360 boolean landscapeOnlyTemp =
361 p.getBoolean("landscape_only", landscapeOnly);
362 if (landscapeOnlyTemp != landscapeOnly) {
363 landscapeOnly = landscapeOnlyTemp;
Leon Scrogginsb0cd0722009-03-31 14:31:22 -0700364 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800365 useWideViewPort = true; // use wide view port for either setting
366 if (autoFitPage) {
367 layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
368 } else {
369 layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL;
370 }
371 defaultTextEncodingName =
372 p.getString(PREF_DEFAULT_TEXT_ENCODING,
373 defaultTextEncodingName);
374
375 showDebugSettings =
376 p.getBoolean(PREF_DEBUG_SETTINGS, showDebugSettings);
377 // Debug menu items have precidence if the menu is visible
378 if (showDebugSettings) {
379 boolean small_screen = p.getBoolean("small_screen",
380 layoutAlgorithm ==
381 WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
382 if (small_screen) {
383 layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN;
384 } else {
385 boolean normal_layout = p.getBoolean("normal_layout",
386 layoutAlgorithm == WebSettings.LayoutAlgorithm.NORMAL);
387 if (normal_layout) {
388 layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL;
389 } else {
390 layoutAlgorithm =
391 WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
392 }
393 }
394 useWideViewPort = p.getBoolean("wide_viewport", useWideViewPort);
395 tracing = p.getBoolean("enable_tracing", tracing);
396 lightTouch = p.getBoolean("enable_light_touch", lightTouch);
397 navDump = p.getBoolean("enable_nav_dump", navDump);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800398 userAgent = Integer.parseInt(p.getString("user_agent", "0"));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800399 }
Feng Qianb3c02da2009-06-29 15:58:08 -0700400 // JS flags is loaded from DB even if showDebugSettings is false,
401 // so that it can be set once and be effective all the time.
402 jsFlags = p.getString("js_engine_flags", "");
Ben Murdochbff2d602009-07-01 20:19:05 +0100403
404 // Read the setting for showing/hiding the JS Console always so that should the
405 // user enable debug settings, we already know if we should show the console.
406 // The user will never see the console unless they navigate to about:debug,
407 // regardless of the setting we read here. This setting is only used after debug
408 // is enabled.
409 showConsole = p.getBoolean("javascript_console", showConsole);
Grace Klobad9ee1392009-07-20 11:53:33 -0700410
Andrei Popescu01068702009-08-03 16:03:24 +0100411 // HTML5 API flags
412 appCacheEnabled = p.getBoolean("enable_appcache", appCacheEnabled);
413 databaseEnabled = p.getBoolean("enable_database", databaseEnabled);
414 domStorageEnabled = p.getBoolean("enable_domstorage", domStorageEnabled);
Steve Blockf344d032009-07-30 10:50:45 +0100415 geolocationEnabled = p.getBoolean("enable_geolocation", geolocationEnabled);
Andrei Popescu01068702009-08-03 16:03:24 +0100416 workersEnabled = p.getBoolean("enable_workers", workersEnabled);
Steve Blockf344d032009-07-30 10:50:45 +0100417
Grace Klobad9ee1392009-07-20 11:53:33 -0700418 update();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800419 }
420
The Android Open Source Project0c908882009-03-03 19:32:16 -0800421 public String getHomePage() {
422 return homeUrl;
423 }
424
Bjorn Bringertd2670652010-09-13 14:06:41 +0100425 public SearchEngine getSearchEngine() {
426 return searchEngine;
427 }
428
Feng Qianb3c02da2009-06-29 15:58:08 -0700429 public String getJsFlags() {
430 return jsFlags;
431 }
432
Andrei Popescu79e82b72009-07-27 12:01:59 +0100433 public WebStorageSizeManager getWebStorageSizeManager() {
434 return webStorageSizeManager;
435 }
436
The Android Open Source Project0c908882009-03-03 19:32:16 -0800437 public void setHomePage(Context context, String url) {
438 Editor ed = PreferenceManager.
439 getDefaultSharedPreferences(context).edit();
440 ed.putString(PREF_HOMEPAGE, url);
Brad Fitzpatrick1a6e0e82010-09-01 16:29:03 -0700441 ed.apply();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800442 homeUrl = url;
443 }
444
The Android Open Source Project0c908882009-03-03 19:32:16 -0800445 public WebSettings.TextSize getTextSize() {
446 return textSize;
447 }
448
Grace Kloba2f830682009-06-25 11:08:53 -0700449 public WebSettings.ZoomDensity getDefaultZoom() {
450 return zoomDensity;
451 }
452
The Android Open Source Project0c908882009-03-03 19:32:16 -0800453 public boolean openInBackground() {
454 return openInBackground;
455 }
456
457 public boolean showSecurityWarnings() {
458 return showSecurityWarnings;
459 }
460
461 public boolean isTracing() {
462 return tracing;
463 }
464
465 public boolean isLightTouch() {
466 return lightTouch;
467 }
468
469 public boolean isNavDump() {
470 return navDump;
471 }
472
The Android Open Source Project0c908882009-03-03 19:32:16 -0800473 public boolean showDebugSettings() {
474 return showDebugSettings;
475 }
476
477 public void toggleDebugSettings() {
478 showDebugSettings = !showDebugSettings;
479 navDump = showDebugSettings;
480 update();
481 }
482
483 /**
484 * Add a WebSettings object to the list of observers that will be updated
485 * when update() is called.
486 *
487 * @param s A WebSettings object that is strictly tied to the life of a
488 * WebView.
489 */
490 public Observer addObserver(WebSettings s) {
491 Observer old = mWebSettingsToObservers.get(s);
492 if (old != null) {
493 super.deleteObserver(old);
494 }
495 Observer o = new Observer(s);
496 mWebSettingsToObservers.put(s, o);
497 super.addObserver(o);
498 return o;
499 }
500
501 /**
502 * Delete the given WebSettings observer from the list of observers.
503 * @param s The WebSettings object to be deleted.
504 */
505 public void deleteObserver(WebSettings s) {
506 Observer o = mWebSettingsToObservers.get(s);
507 if (o != null) {
508 mWebSettingsToObservers.remove(s);
509 super.deleteObserver(o);
510 }
511 }
512
513 /*
514 * Package level method for obtaining a single app instance of the
515 * BrowserSettings.
516 */
517 /*package*/ static BrowserSettings getInstance() {
518 if (sSingleton == null ) {
519 sSingleton = new BrowserSettings();
520 }
521 return sSingleton;
522 }
523
524 /*
525 * Package level method for associating the BrowserSettings with TabControl
526 */
527 /* package */void setTabControl(TabControl tabControl) {
528 mTabControl = tabControl;
Shimeng (Simon) Wang161974f2010-03-09 14:30:07 -0800529 updateTabControlSettings();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800530 }
531
532 /*
533 * Update all the observers of the object.
534 */
535 /*package*/ void update() {
536 setChanged();
537 notifyObservers();
538 }
539
540 /*package*/ void clearCache(Context context) {
541 WebIconDatabase.getInstance().removeAllIcons();
542 if (mTabControl != null) {
543 WebView current = mTabControl.getCurrentWebView();
544 if (current != null) {
545 current.clearCache(true);
546 }
547 }
548 }
549
550 /*package*/ void clearCookies(Context context) {
551 CookieManager.getInstance().removeAllCookie();
552 }
553
554 /* package */void clearHistory(Context context) {
555 ContentResolver resolver = context.getContentResolver();
556 Browser.clearHistory(resolver);
557 Browser.clearSearches(resolver);
558 }
559
560 /* package */ void clearFormData(Context context) {
561 WebViewDatabase.getInstance(context).clearFormData();
562 if (mTabControl != null) {
Henrik Baard794dc722010-02-19 16:28:06 +0100563 WebView currentTopView = mTabControl.getCurrentTopWebView();
564 if (currentTopView != null) {
565 currentTopView.clearFormData();
566 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800567 }
568 }
569
570 /*package*/ void clearPasswords(Context context) {
571 WebViewDatabase db = WebViewDatabase.getInstance(context);
572 db.clearUsernamePassword();
573 db.clearHttpAuthUsernamePassword();
574 }
575
Shimeng (Simon) Wang161974f2010-03-09 14:30:07 -0800576 private void updateTabControlSettings() {
577 // Enable/disable the error console.
578 mTabControl.getBrowserActivity().setShouldShowErrorConsole(
579 showDebugSettings && showConsole);
580 mTabControl.getBrowserActivity().setRequestedOrientation(
581 landscapeOnly ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
582 : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
583 }
584
Steve Blockf344d032009-07-30 10:50:45 +0100585 private void maybeDisableWebsiteSettings(Context context) {
Nicolas Roard99b3ae12009-09-22 15:17:52 +0100586 PreferenceActivity activity = (PreferenceActivity) context;
587 final PreferenceScreen screen = (PreferenceScreen)
588 activity.findPreference(BrowserSettings.PREF_WEBSITE_SETTINGS);
589 screen.setEnabled(false);
590 WebStorage.getInstance().getOrigins(new ValueCallback<Map>() {
591 public void onReceiveValue(Map webStorageOrigins) {
592 if ((webStorageOrigins != null) && !webStorageOrigins.isEmpty()) {
593 screen.setEnabled(true);
594 }
595 }
596 });
597
Steve Block2a6a0f42009-11-19 15:55:42 +0000598 GeolocationPermissions.getInstance().getOrigins(new ValueCallback<Set<String> >() {
599 public void onReceiveValue(Set<String> geolocationOrigins) {
Nicolas Roard99b3ae12009-09-22 15:17:52 +0100600 if ((geolocationOrigins != null) && !geolocationOrigins.isEmpty()) {
601 screen.setEnabled(true);
602 }
603 }
604 });
Steve Blockf344d032009-07-30 10:50:45 +0100605 }
606
Nicolas Roard78a98e42009-05-11 13:34:17 +0100607 /*package*/ void clearDatabases(Context context) {
Andrei Popescu824faeb2009-07-21 18:24:06 +0100608 WebStorage.getInstance().deleteAllData();
Steve Blockf344d032009-07-30 10:50:45 +0100609 maybeDisableWebsiteSettings(context);
610 }
611
612 /*package*/ void clearLocationAccess(Context context) {
613 GeolocationPermissions.getInstance().clearAll();
614 maybeDisableWebsiteSettings(context);
Nicolas Roard78a98e42009-05-11 13:34:17 +0100615 }
616
Leon Scroggins9ac587d2009-04-20 12:53:46 -0400617 /*package*/ void resetDefaultPreferences(Context ctx) {
Shimeng (Simon) Wangf7392712010-03-10 16:44:31 -0800618 reset();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800619 SharedPreferences p =
Leon Scroggins9ac587d2009-04-20 12:53:46 -0400620 PreferenceManager.getDefaultSharedPreferences(ctx);
Brad Fitzpatrick1a6e0e82010-09-01 16:29:03 -0700621 p.edit().clear().apply();
Leon Scroggins9ac587d2009-04-20 12:53:46 -0400622 PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences,
The Android Open Source Project0c908882009-03-03 19:32:16 -0800623 true);
Grace Klobaf2c5c1b2009-05-26 10:48:31 -0700624 // reset homeUrl
Grace Klobaa3f90f02009-05-26 11:32:53 -0700625 setHomePage(ctx, getFactoryResetHomeUrl(ctx));
Andrei Popescu79e82b72009-07-27 12:01:59 +0100626 // reset appcache max size
627 appCacheMaxSize = webStorageSizeManager.getAppCacheMaxSize();
Grace Klobaf2c5c1b2009-05-26 10:48:31 -0700628 }
629
630 private String getFactoryResetHomeUrl(Context context) {
631 String url = context.getResources().getString(R.string.homepage_base);
632 if (url.indexOf("{CID}") != -1) {
Patrick Scott43914692010-02-19 10:10:10 -0500633 url = url.replace("{CID}",
634 BrowserProvider.getClientId(context.getContentResolver()));
Grace Klobaf2c5c1b2009-05-26 10:48:31 -0700635 }
636 return url;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800637 }
638
The Android Open Source Project0c908882009-03-03 19:32:16 -0800639 // Private constructor that does nothing.
640 private BrowserSettings() {
Shimeng (Simon) Wangf7392712010-03-10 16:44:31 -0800641 reset();
642 }
643
644 private void reset() {
645 // Private variables for settings
646 // NOTE: these defaults need to be kept in sync with the XML
647 // until the performance of PreferenceManager.setDefaultValues()
648 // is improved.
649 loadsImagesAutomatically = true;
650 javaScriptEnabled = true;
Patrick Scotte536b332010-03-22 10:19:32 -0400651 pluginState = WebSettings.PluginState.ON;
Shimeng (Simon) Wangf7392712010-03-10 16:44:31 -0800652 javaScriptCanOpenWindowsAutomatically = false;
653 showSecurityWarnings = true;
654 rememberPasswords = true;
655 saveFormData = true;
656 openInBackground = false;
Shimeng (Simon) Wangf7392712010-03-10 16:44:31 -0800657 autoFitPage = true;
658 landscapeOnly = false;
659 loadsPageInOverviewMode = true;
660 showDebugSettings = false;
661 // HTML5 API flags
662 appCacheEnabled = true;
663 databaseEnabled = true;
664 domStorageEnabled = true;
665 geolocationEnabled = true;
666 workersEnabled = true; // only affects V8. JSC does not have a similar setting
The Android Open Source Project0c908882009-03-03 19:32:16 -0800667 }
Ed Tam8ba13bc2011-05-05 16:19:48 -0700668
669 /*package*/ String getRlzValue() {
670 return mRlzValue;
671 }
672
673 /*package*/ void updateRlzValues(Context context) {
674 // Use AsyncTask because this queries both RlzProvider and Bookmarks URIs
675 new RlzUpdateTask(context).execute();
676 }
677
678 private class RlzUpdateTask extends AsyncTask<Void, Void, Void> {
679 private final Context context;
680
681 public RlzUpdateTask(Context context) {
682 this.context = context;
683 }
684
685 @Override
686 protected Void doInBackground(Void...unused) {
687 String rlz = retrieveRlzValue(context);
688 if (!rlz.isEmpty()) {
689 mRlzValue = rlz;
690 updateHomePageRlzParameter(context);
691 updateBookmarksRlzParameter(context);
692 }
693 return null;
694 }
695 }
696
697 // Update RLZ value if present in Home page
698 private void updateHomePageRlzParameter(Context context) {
699 Uri uri = Uri.parse(homeUrl);
700 if ((uri.getQueryParameter("rlz") != null) && UrlUtils.isGoogleUri(uri)) {
701 String newHomeUrl = updateRlzParameter(homeUrl);
702 if (!homeUrl.equals(newHomeUrl)) {
703 setHomePage(context, newHomeUrl);
704 }
705 }
706 }
707
708 // Update RLZ value if present in bookmarks
709 private void updateBookmarksRlzParameter(Context context) {
710 Cursor cur = null;
711 try {
712 cur = context.getContentResolver().query(Browser.BOOKMARKS_URI,
713 new String[] { BookmarkColumns._ID, BookmarkColumns.URL },
714 "url LIKE '%rlz=%'", null, null);
715 if ((cur == null) || (cur.getCount() == 0)) {
716 return;
717 }
718 for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) {
719 long id = cur.getLong(0);
720 String url = cur.getString(1);
721 if ((url == null) || url.isEmpty()) {
722 continue;
723 }
724
725 Uri uri = Uri.parse(url);
726 if ((uri.getQueryParameter("rlz") != null) && UrlUtils.isGoogleUri(uri)) {
727 String newUrl = updateRlzParameter(url);
728 if (!url.equals(newUrl)) {
729 ContentValues values = new ContentValues();
730 values.put(BookmarkColumns.URL, newUrl);
731 Uri bookmarkUri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI, id);
732 context.getContentResolver().update(bookmarkUri, values, null, null);
733 }
734 }
735 }
736 } finally {
737 if (cur != null) {
738 cur.close();
739 }
740 }
741 }
742
743 private String updateRlzParameter(String url) {
744 Uri uri = Uri.parse(url);
745 String oldRlz = uri.getQueryParameter("rlz");
746 if (oldRlz != null) {
747 return url.replace("rlz=" + oldRlz, "rlz=" + mRlzValue);
748 }
749 return url;
750 }
751
752 // Retrieve the RLZ value from the Rlz Provider
753 private static String retrieveRlzValue(Context context) {
754 String rlz = "";
755 PackageManager pm = context.getPackageManager();
756 if (pm.resolveContentProvider(RLZ_PROVIDER, 0) == null) {
757 return rlz;
758 }
759
760 String ap = context.getResources().getString(R.string.rlz_access_point);
761 if (ap.isEmpty()) {
762 return rlz;
763 }
764
765 Uri rlzUri = Uri.withAppendedPath(RLZ_PROVIDER_URI, ap);
766 Cursor cur = null;
767 try {
768 cur = context.getContentResolver().query(rlzUri, null, null, null, null);
769 if (cur != null && cur.moveToFirst() && !cur.isNull(0)) {
770 rlz = cur.getString(0);
771 }
772 } finally {
773 if (cur != null) {
774 cur.close();
775 }
776 }
777 return rlz;
778 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800779}