BrowserSettings.java revision b7775e1e46a6c8ce0f07747d44c1b1792bb0ce1c
1/*
2 * Copyright (C) 2007 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
17package com.android.browser;
18
19import android.app.Activity;
20import android.content.ContentResolver;
21import android.content.Context;
22import android.content.pm.ActivityInfo;
23import android.content.SharedPreferences;
24import android.content.SharedPreferences.Editor;
25import android.os.SystemProperties;
26import android.view.WindowManager;
27import android.webkit.CacheManager;
28import android.webkit.CookieManager;
29import android.webkit.WebViewDatabase;
30import android.webkit.WebIconDatabase;
31import android.webkit.WebSettings;
32import android.preference.PreferenceManager;
33import android.provider.Browser;
34
35import java.util.HashMap;
36import java.util.Observable;
37
38/*
39 * Package level class for storing various WebView and Browser settings. To use
40 * this class:
41 * BrowserSettings s = BrowserSettings.getInstance();
42 * s.addObserver(webView.getSettings());
43 * s.loadFromDb(context); // Only needed on app startup
44 * s.javaScriptEnabled = true;
45 * ... // set any other settings
46 * s.update(); // this will update all the observers
47 *
48 * To remove an observer:
49 * s.deleteObserver(webView.getSettings());
50 */
51class BrowserSettings extends Observable {
52
53    // Public variables for settings
54    // NOTE: these defaults need to be kept in sync with the XML
55    // until the performance of PreferenceManager.setDefaultValues()
56    // is improved.
57    private boolean loadsImagesAutomatically = true;
58    private boolean javaScriptEnabled = true;
59    private boolean pluginsEnabled = true;
60    private String pluginsPath;  // default value set in loadFromDb().
61    private boolean javaScriptCanOpenWindowsAutomatically = false;
62    private boolean showSecurityWarnings = true;
63    private boolean rememberPasswords = true;
64    private boolean saveFormData = true;
65    private boolean openInBackground = false;
66    private String defaultTextEncodingName;
67    private String homeUrl = "http://www.google.com/m?client=ms-" +
68        SystemProperties.get("ro.com.google.clientid", "unknown");
69    private boolean loginInitialized = false;
70    private boolean autoFitPage = true;
71    private boolean showDebugSettings = false;
72
73    // Development settings
74    public WebSettings.LayoutAlgorithm layoutAlgorithm =
75        WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
76    private boolean useWideViewPort = true;
77    private int userAgent = 0;
78    private boolean tracing = false;
79    private boolean lightTouch = false;
80    private boolean navDump = false;
81    // Browser only settings
82    private boolean doFlick = false;
83
84    // Private preconfigured values
85    private static int minimumFontSize = 8;
86    private static int minimumLogicalFontSize = 8;
87    private static int defaultFontSize = 16;
88    private static int defaultFixedFontSize = 13;
89    private static WebSettings.TextSize textSize =
90        WebSettings.TextSize.NORMAL;
91
92    // Preference keys that are used outside this class
93    public final static String PREF_CLEAR_CACHE = "privacy_clear_cache";
94    public final static String PREF_CLEAR_COOKIES = "privacy_clear_cookies";
95    public final static String PREF_CLEAR_HISTORY = "privacy_clear_history";
96    public final static String PREF_HOMEPAGE = "homepage";
97    public final static String PREF_CLEAR_FORM_DATA =
98            "privacy_clear_form_data";
99    public final static String PREF_CLEAR_PASSWORDS =
100            "privacy_clear_passwords";
101    public final static String PREF_EXTRAS_RESET_DEFAULTS =
102            "reset_default_preferences";
103    public final static String PREF_DEBUG_SETTINGS = "debug_menu";
104    public final static String PREF_GEARS_SETTINGS = "gears_settings";
105    public final static String PREF_TEXT_SIZE = "text_size";
106    public final static String PREF_DEFAULT_TEXT_ENCODING =
107            "default_text_encoding";
108
109    private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " +
110            "U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.18 (KHTML, " +
111            "like Gecko) Version/3.1.2 Safari/525.20.1";
112
113    private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " +
114            "CPU iPhone OS 2_2 like Mac OS X; en-us) AppleWebKit/525.18.1 " +
115            "(KHTML, like Gecko) Version/3.1.1 Mobile/5G77 Safari/525.20";
116
117    // Value to truncate strings when adding them to a TextView within
118    // a ListView
119    public final static int MAX_TEXTVIEW_LEN = 80;
120
121    private TabControl mTabControl;
122
123    // Single instance of the BrowserSettings for use in the Browser app.
124    private static BrowserSettings sSingleton;
125
126    // Private map of WebSettings to Observer objects used when deleting an
127    // observer.
128    private HashMap<WebSettings,Observer> mWebSettingsToObservers =
129        new HashMap<WebSettings,Observer>();
130
131    /*
132     * An observer wrapper for updating a WebSettings object with the new
133     * settings after a call to BrowserSettings.update().
134     */
135    static class Observer implements java.util.Observer {
136        // Private WebSettings object that will be updated.
137        private WebSettings mSettings;
138
139        Observer(WebSettings w) {
140            mSettings = w;
141        }
142
143        public void update(Observable o, Object arg) {
144            BrowserSettings b = (BrowserSettings)o;
145            WebSettings s = mSettings;
146
147            s.setLayoutAlgorithm(b.layoutAlgorithm);
148            if (b.userAgent == 0) {
149                // use the default ua string
150                s.setUserAgentString(null);
151            } else if (b.userAgent == 1) {
152                s.setUserAgentString(DESKTOP_USERAGENT);
153            } else if (b.userAgent == 2) {
154                s.setUserAgentString(IPHONE_USERAGENT);
155            }
156            s.setUseWideViewPort(b.useWideViewPort);
157            s.setLoadsImagesAutomatically(b.loadsImagesAutomatically);
158            s.setJavaScriptEnabled(b.javaScriptEnabled);
159            s.setPluginsEnabled(b.pluginsEnabled);
160            s.setPluginsPath(b.pluginsPath);
161            s.setJavaScriptCanOpenWindowsAutomatically(
162                    b.javaScriptCanOpenWindowsAutomatically);
163            s.setDefaultTextEncodingName(b.defaultTextEncodingName);
164            s.setMinimumFontSize(b.minimumFontSize);
165            s.setMinimumLogicalFontSize(b.minimumLogicalFontSize);
166            s.setDefaultFontSize(b.defaultFontSize);
167            s.setDefaultFixedFontSize(b.defaultFixedFontSize);
168            s.setNavDump(b.navDump);
169            s.setTextSize(b.textSize);
170            s.setLightTouchEnabled(b.lightTouch);
171            s.setSaveFormData(b.saveFormData);
172            s.setSavePassword(b.rememberPasswords);
173
174            // WebView inside Browser doesn't want initial focus to be set.
175            s.setNeedInitialFocus(false);
176            // Browser supports multiple windows
177            s.setSupportMultipleWindows(true);
178            // Turn off file access
179            s.setAllowFileAccess(false);
180        }
181    }
182
183    /**
184     * Load settings from the browser app's database.
185     * NOTE: Strings used for the preferences must match those specified
186     * in the browser_preferences.xml
187     * @param ctx A Context object used to query the browser's settings
188     *            database. If the database exists, the saved settings will be
189     *            stored in this BrowserSettings object. This will update all
190     *            observers of this object.
191     */
192    public void loadFromDb(Context ctx) {
193        SharedPreferences p =
194                PreferenceManager.getDefaultSharedPreferences(ctx);
195
196        // Set the default value for the plugins path to the application's
197        // local directory.
198        pluginsPath = ctx.getDir("plugins", 0).getPath();
199
200        // Load the defaults from the xml
201        // This call is TOO SLOW, need to manually keep the defaults
202        // in sync
203        //PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences);
204        syncSharedPreferences(p);
205    }
206
207    /* package */ void syncSharedPreferences(SharedPreferences p) {
208        homeUrl =
209            p.getString(PREF_HOMEPAGE, homeUrl);
210        loadsImagesAutomatically = p.getBoolean("load_images",
211                loadsImagesAutomatically);
212        javaScriptEnabled = p.getBoolean("enable_javascript",
213                javaScriptEnabled);
214        pluginsEnabled = p.getBoolean("enable_plugins",
215                pluginsEnabled);
216        pluginsPath = p.getString("plugins_path", pluginsPath);
217        javaScriptCanOpenWindowsAutomatically = !p.getBoolean(
218            "block_popup_windows",
219            !javaScriptCanOpenWindowsAutomatically);
220        showSecurityWarnings = p.getBoolean("show_security_warnings",
221                showSecurityWarnings);
222        rememberPasswords = p.getBoolean("remember_passwords",
223                rememberPasswords);
224        saveFormData = p.getBoolean("save_formdata",
225                saveFormData);
226        boolean accept_cookies = p.getBoolean("accept_cookies",
227                CookieManager.getInstance().acceptCookie());
228        CookieManager.getInstance().setAcceptCookie(accept_cookies);
229        openInBackground = p.getBoolean("open_in_background", openInBackground);
230        loginInitialized = p.getBoolean("login_initialized", loginInitialized);
231        textSize = WebSettings.TextSize.valueOf(
232                p.getString(PREF_TEXT_SIZE, textSize.name()));
233        autoFitPage = p.getBoolean("autofit_pages", autoFitPage);
234        useWideViewPort = true; // use wide view port for either setting
235        if (autoFitPage) {
236            layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
237        } else {
238            layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL;
239        }
240        defaultTextEncodingName =
241                p.getString(PREF_DEFAULT_TEXT_ENCODING,
242                        defaultTextEncodingName);
243
244        showDebugSettings =
245                p.getBoolean(PREF_DEBUG_SETTINGS, showDebugSettings);
246        // Debug menu items have precidence if the menu is visible
247        if (showDebugSettings) {
248            boolean small_screen = p.getBoolean("small_screen",
249                    layoutAlgorithm ==
250                    WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
251            if (small_screen) {
252                layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN;
253            } else {
254                boolean normal_layout = p.getBoolean("normal_layout",
255                        layoutAlgorithm == WebSettings.LayoutAlgorithm.NORMAL);
256                if (normal_layout) {
257                    layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL;
258                } else {
259                    layoutAlgorithm =
260                            WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
261                }
262            }
263            useWideViewPort = p.getBoolean("wide_viewport", useWideViewPort);
264            tracing = p.getBoolean("enable_tracing", tracing);
265            lightTouch = p.getBoolean("enable_light_touch", lightTouch);
266            navDump = p.getBoolean("enable_nav_dump", navDump);
267            doFlick = p.getBoolean("enable_flick", doFlick);
268            userAgent = Integer.parseInt(p.getString("user_agent", "0"));
269            mTabControl.getBrowserActivity().setBaseSearchUrl(
270                    p.getString("search_url", ""));
271        }
272        update();
273    }
274
275    public String getPluginsPath() {
276        return pluginsPath;
277    }
278
279    public String getHomePage() {
280        return homeUrl;
281    }
282
283    public void setHomePage(Context context, String url) {
284        Editor ed = PreferenceManager.
285                getDefaultSharedPreferences(context).edit();
286        ed.putString(PREF_HOMEPAGE, url);
287        ed.commit();
288        homeUrl = url;
289    }
290
291    public boolean isLoginInitialized() {
292        return loginInitialized;
293    }
294
295    public void setLoginInitialized(Context context) {
296        loginInitialized = true;
297        Editor ed = PreferenceManager.
298                getDefaultSharedPreferences(context).edit();
299        ed.putBoolean("login_initialized", loginInitialized);
300        ed.commit();
301    }
302
303    public WebSettings.TextSize getTextSize() {
304        return textSize;
305    }
306
307    public boolean openInBackground() {
308        return openInBackground;
309    }
310
311    public boolean showSecurityWarnings() {
312        return showSecurityWarnings;
313    }
314
315    public boolean isTracing() {
316        return tracing;
317    }
318
319    public boolean isLightTouch() {
320        return lightTouch;
321    }
322
323    public boolean isNavDump() {
324        return navDump;
325    }
326
327    public boolean doFlick() {
328        return doFlick;
329    }
330
331    public boolean showDebugSettings() {
332        return showDebugSettings;
333    }
334
335    public void toggleDebugSettings() {
336        showDebugSettings = !showDebugSettings;
337    }
338
339    /**
340     * Add a WebSettings object to the list of observers that will be updated
341     * when update() is called.
342     *
343     * @param s A WebSettings object that is strictly tied to the life of a
344     *            WebView.
345     */
346    public Observer addObserver(WebSettings s) {
347        Observer old = mWebSettingsToObservers.get(s);
348        if (old != null) {
349            super.deleteObserver(old);
350        }
351        Observer o = new Observer(s);
352        mWebSettingsToObservers.put(s, o);
353        super.addObserver(o);
354        return o;
355    }
356
357    /**
358     * Delete the given WebSettings observer from the list of observers.
359     * @param s The WebSettings object to be deleted.
360     */
361    public void deleteObserver(WebSettings s) {
362        Observer o = mWebSettingsToObservers.get(s);
363        if (o != null) {
364            mWebSettingsToObservers.remove(s);
365            super.deleteObserver(o);
366        }
367    }
368
369    /*
370     * Package level method for obtaining a single app instance of the
371     * BrowserSettings.
372     */
373    /*package*/ static BrowserSettings getInstance() {
374        if (sSingleton == null ) {
375            sSingleton = new BrowserSettings();
376        }
377        return sSingleton;
378    }
379
380    /*
381     * Package level method for associating the BrowserSettings with TabControl
382     */
383    /* package */void setTabControl(TabControl tabControl) {
384        mTabControl = tabControl;
385    }
386
387    /*
388     * Update all the observers of the object.
389     */
390    /*package*/ void update() {
391        setChanged();
392        notifyObservers();
393    }
394
395    /*package*/ void clearCache(Context context) {
396        WebIconDatabase.getInstance().removeAllIcons();
397        if (mTabControl != null) {
398            mTabControl.getCurrentWebView().clearCache(true);
399        }
400    }
401
402    /*package*/ void clearCookies(Context context) {
403        CookieManager.getInstance().removeAllCookie();
404    }
405
406    /* package */void clearHistory(Context context) {
407        ContentResolver resolver = context.getContentResolver();
408        Browser.clearHistory(resolver);
409        Browser.clearSearches(resolver);
410    }
411
412    /* package */ void clearFormData(Context context) {
413        WebViewDatabase.getInstance(context).clearFormData();
414        if (mTabControl != null) {
415            mTabControl.getCurrentTopWebView().clearFormData();
416        }
417    }
418
419    /*package*/ void clearPasswords(Context context) {
420        WebViewDatabase db = WebViewDatabase.getInstance(context);
421        db.clearUsernamePassword();
422        db.clearHttpAuthUsernamePassword();
423    }
424
425    /*package*/ void resetDefaultPreferences(Context context) {
426        SharedPreferences p =
427            PreferenceManager.getDefaultSharedPreferences(context);
428        p.edit().clear().commit();
429        PreferenceManager.setDefaultValues(context, R.xml.browser_preferences,
430                true);
431    }
432
433    // Private constructor that does nothing.
434    private BrowserSettings() {
435    }
436}
437