OSDN Git Service

am 9c50b60c: (-s ours) Import revised translations. DO NOT MERGE
[android-x86/packages-apps-Browser.git] / src / com / android / browser / BrowserSettings.java
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.google.android.providers.GoogleSettings.Partner;
21
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.content.pm.ActivityInfo;
25 import android.content.SharedPreferences;
26 import android.content.SharedPreferences.Editor;
27 import android.preference.PreferenceActivity;
28 import android.preference.PreferenceScreen;
29 import android.webkit.CookieManager;
30 import android.webkit.GeolocationPermissions;
31 import android.webkit.ValueCallback;
32 import android.webkit.WebView;
33 import android.webkit.WebViewDatabase;
34 import android.webkit.WebIconDatabase;
35 import android.webkit.WebSettings;
36 import android.webkit.WebStorage;
37 import android.preference.PreferenceManager;
38 import android.provider.Browser;
39
40 import java.util.HashMap;
41 import java.util.Map;
42 import java.util.Set;
43 import java.util.Observable;
44
45 /*
46  * Package level class for storing various WebView and Browser settings. To use
47  * this class:
48  * BrowserSettings s = BrowserSettings.getInstance();
49  * s.addObserver(webView.getSettings());
50  * s.loadFromDb(context); // Only needed on app startup
51  * s.javaScriptEnabled = true;
52  * ... // set any other settings
53  * s.update(); // this will update all the observers
54  *
55  * To remove an observer:
56  * s.deleteObserver(webView.getSettings());
57  */
58 class BrowserSettings extends Observable {
59
60     // Private variables for settings
61     // NOTE: these defaults need to be kept in sync with the XML
62     // until the performance of PreferenceManager.setDefaultValues()
63     // is improved.
64     private boolean loadsImagesAutomatically = true;
65     private boolean javaScriptEnabled = true;
66     private boolean pluginsEnabled = true;
67     private boolean javaScriptCanOpenWindowsAutomatically = false;
68     private boolean showSecurityWarnings = true;
69     private boolean rememberPasswords = true;
70     private boolean saveFormData = true;
71     private boolean openInBackground = false;
72     private String defaultTextEncodingName;
73     private String homeUrl = "";
74     private boolean loginInitialized = false;
75     private boolean autoFitPage = true;
76     private boolean landscapeOnly = false;
77     private boolean loadsPageInOverviewMode = true;
78     private boolean showDebugSettings = false;
79     // HTML5 API flags
80     private boolean appCacheEnabled = true;
81     private boolean databaseEnabled = true;
82     private boolean domStorageEnabled = true;
83     private boolean geolocationEnabled = true;
84     private boolean workersEnabled = true;  // only affects V8. JSC does not have a similar setting
85     // HTML5 API configuration params
86     private long appCacheMaxSize = Long.MAX_VALUE;
87     private String appCachePath;  // default value set in loadFromDb().
88     private String databasePath; // default value set in loadFromDb()
89     private String geolocationDatabasePath; // default value set in loadFromDb()
90     private WebStorageSizeManager webStorageSizeManager;
91
92     private String jsFlags = "";
93
94     private final static String TAG = "BrowserSettings";
95
96     // Development settings
97     public WebSettings.LayoutAlgorithm layoutAlgorithm =
98         WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
99     private boolean useWideViewPort = true;
100     private int userAgent = 0;
101     private boolean tracing = false;
102     private boolean lightTouch = false;
103     private boolean navDump = false;
104
105     // By default the error console is shown once the user navigates to about:debug.
106     // The setting can be then toggled from the settings menu.
107     private boolean showConsole = true;
108
109     // Private preconfigured values
110     private static int minimumFontSize = 8;
111     private static int minimumLogicalFontSize = 8;
112     private static int defaultFontSize = 16;
113     private static int defaultFixedFontSize = 13;
114     private static WebSettings.TextSize textSize =
115         WebSettings.TextSize.NORMAL;
116     private static WebSettings.ZoomDensity zoomDensity =
117         WebSettings.ZoomDensity.MEDIUM;
118
119     // Preference keys that are used outside this class
120     public final static String PREF_CLEAR_CACHE = "privacy_clear_cache";
121     public final static String PREF_CLEAR_COOKIES = "privacy_clear_cookies";
122     public final static String PREF_CLEAR_HISTORY = "privacy_clear_history";
123     public final static String PREF_HOMEPAGE = "homepage";
124     public final static String PREF_CLEAR_FORM_DATA =
125             "privacy_clear_form_data";
126     public final static String PREF_CLEAR_PASSWORDS =
127             "privacy_clear_passwords";
128     public final static String PREF_EXTRAS_RESET_DEFAULTS =
129             "reset_default_preferences";
130     public final static String PREF_DEBUG_SETTINGS = "debug_menu";
131     public final static String PREF_WEBSITE_SETTINGS = "website_settings";
132     public final static String PREF_TEXT_SIZE = "text_size";
133     public final static String PREF_DEFAULT_ZOOM = "default_zoom";
134     public final static String PREF_DEFAULT_TEXT_ENCODING =
135             "default_text_encoding";
136     public final static String PREF_CLEAR_GEOLOCATION_ACCESS =
137             "privacy_clear_geolocation_access";
138
139     private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " +
140             "U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.17 (KHTML, " +
141             "like Gecko) Version/4.0 Safari/530.17";
142
143     private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " +
144             "CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 " +
145             "(KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16";
146
147     // Value to truncate strings when adding them to a TextView within
148     // a ListView
149     public final static int MAX_TEXTVIEW_LEN = 80;
150
151     private TabControl mTabControl;
152
153     // Single instance of the BrowserSettings for use in the Browser app.
154     private static BrowserSettings sSingleton;
155
156     // Private map of WebSettings to Observer objects used when deleting an
157     // observer.
158     private HashMap<WebSettings,Observer> mWebSettingsToObservers =
159         new HashMap<WebSettings,Observer>();
160
161     /*
162      * An observer wrapper for updating a WebSettings object with the new
163      * settings after a call to BrowserSettings.update().
164      */
165     static class Observer implements java.util.Observer {
166         // Private WebSettings object that will be updated.
167         private WebSettings mSettings;
168
169         Observer(WebSettings w) {
170             mSettings = w;
171         }
172
173         public void update(Observable o, Object arg) {
174             BrowserSettings b = (BrowserSettings)o;
175             WebSettings s = mSettings;
176
177             s.setLayoutAlgorithm(b.layoutAlgorithm);
178             if (b.userAgent == 0) {
179                 // use the default ua string
180                 s.setUserAgentString(null);
181             } else if (b.userAgent == 1) {
182                 s.setUserAgentString(DESKTOP_USERAGENT);
183             } else if (b.userAgent == 2) {
184                 s.setUserAgentString(IPHONE_USERAGENT);
185             }
186             s.setUseWideViewPort(b.useWideViewPort);
187             s.setLoadsImagesAutomatically(b.loadsImagesAutomatically);
188             s.setJavaScriptEnabled(b.javaScriptEnabled);
189             s.setPluginsEnabled(b.pluginsEnabled);
190             s.setJavaScriptCanOpenWindowsAutomatically(
191                     b.javaScriptCanOpenWindowsAutomatically);
192             s.setDefaultTextEncodingName(b.defaultTextEncodingName);
193             s.setMinimumFontSize(b.minimumFontSize);
194             s.setMinimumLogicalFontSize(b.minimumLogicalFontSize);
195             s.setDefaultFontSize(b.defaultFontSize);
196             s.setDefaultFixedFontSize(b.defaultFixedFontSize);
197             s.setNavDump(b.navDump);
198             s.setTextSize(b.textSize);
199             s.setDefaultZoom(b.zoomDensity);
200             s.setLightTouchEnabled(b.lightTouch);
201             s.setSaveFormData(b.saveFormData);
202             s.setSavePassword(b.rememberPasswords);
203             s.setLoadWithOverviewMode(b.loadsPageInOverviewMode);
204
205             // WebView inside Browser doesn't want initial focus to be set.
206             s.setNeedInitialFocus(false);
207             // Browser supports multiple windows
208             s.setSupportMultipleWindows(true);
209
210             // HTML5 API flags
211             s.setAppCacheEnabled(b.appCacheEnabled);
212             s.setDatabaseEnabled(b.databaseEnabled);
213             s.setDomStorageEnabled(b.domStorageEnabled);
214             s.setWorkersEnabled(b.workersEnabled);  // This only affects V8.
215             s.setGeolocationEnabled(b.geolocationEnabled);
216
217             // HTML5 configuration parameters.
218             s.setAppCacheMaxSize(b.appCacheMaxSize);
219             s.setAppCachePath(b.appCachePath);
220             s.setDatabasePath(b.databasePath);
221             s.setGeolocationDatabasePath(b.geolocationDatabasePath);
222
223             // Enable/Disable the error console.
224             b.mTabControl.getBrowserActivity().setShouldShowErrorConsole(
225                     b.showDebugSettings && b.showConsole);
226         }
227     }
228
229     /**
230      * Load settings from the browser app's database.
231      * NOTE: Strings used for the preferences must match those specified
232      * in the browser_preferences.xml
233      * @param ctx A Context object used to query the browser's settings
234      *            database. If the database exists, the saved settings will be
235      *            stored in this BrowserSettings object. This will update all
236      *            observers of this object.
237      */
238     public void loadFromDb(Context ctx) {
239         SharedPreferences p =
240                 PreferenceManager.getDefaultSharedPreferences(ctx);
241         // Set the default value for the Application Caches path.
242         appCachePath = ctx.getDir("appcache", 0).getPath();
243         // Determine the maximum size of the application cache.
244         webStorageSizeManager = new WebStorageSizeManager(
245                 ctx,
246                 new WebStorageSizeManager.StatFsDiskInfo(appCachePath),
247                 new WebStorageSizeManager.WebKitAppCacheInfo(appCachePath));
248         appCacheMaxSize = webStorageSizeManager.getAppCacheMaxSize();
249         // Set the default value for the Database path.
250         databasePath = ctx.getDir("databases", 0).getPath();
251         // Set the default value for the Geolocation database path.
252         geolocationDatabasePath = ctx.getDir("geolocation", 0).getPath();
253
254         homeUrl = getFactoryResetHomeUrl(ctx);
255
256         // Load the defaults from the xml
257         // This call is TOO SLOW, need to manually keep the defaults
258         // in sync
259         //PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences);
260         syncSharedPreferences(p);
261     }
262
263     /* package */ void syncSharedPreferences(SharedPreferences p) {
264
265         homeUrl =
266             p.getString(PREF_HOMEPAGE, homeUrl);
267
268         loadsImagesAutomatically = p.getBoolean("load_images",
269                 loadsImagesAutomatically);
270         javaScriptEnabled = p.getBoolean("enable_javascript",
271                 javaScriptEnabled);
272         pluginsEnabled = p.getBoolean("enable_plugins",
273                 pluginsEnabled);
274         javaScriptCanOpenWindowsAutomatically = !p.getBoolean(
275             "block_popup_windows",
276             !javaScriptCanOpenWindowsAutomatically);
277         showSecurityWarnings = p.getBoolean("show_security_warnings",
278                 showSecurityWarnings);
279         rememberPasswords = p.getBoolean("remember_passwords",
280                 rememberPasswords);
281         saveFormData = p.getBoolean("save_formdata",
282                 saveFormData);
283         boolean accept_cookies = p.getBoolean("accept_cookies",
284                 CookieManager.getInstance().acceptCookie());
285         CookieManager.getInstance().setAcceptCookie(accept_cookies);
286         openInBackground = p.getBoolean("open_in_background", openInBackground);
287         loginInitialized = p.getBoolean("login_initialized", loginInitialized);
288         textSize = WebSettings.TextSize.valueOf(
289                 p.getString(PREF_TEXT_SIZE, textSize.name()));
290         zoomDensity = WebSettings.ZoomDensity.valueOf(
291                 p.getString(PREF_DEFAULT_ZOOM, zoomDensity.name()));
292         autoFitPage = p.getBoolean("autofit_pages", autoFitPage);
293         loadsPageInOverviewMode = p.getBoolean("load_page",
294                 loadsPageInOverviewMode);
295         boolean landscapeOnlyTemp =
296                 p.getBoolean("landscape_only", landscapeOnly);
297         if (landscapeOnlyTemp != landscapeOnly) {
298             landscapeOnly = landscapeOnlyTemp;
299             mTabControl.getBrowserActivity().setRequestedOrientation(
300                     landscapeOnly ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
301                     : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
302         }
303         useWideViewPort = true; // use wide view port for either setting
304         if (autoFitPage) {
305             layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
306         } else {
307             layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL;
308         }
309         defaultTextEncodingName =
310                 p.getString(PREF_DEFAULT_TEXT_ENCODING,
311                         defaultTextEncodingName);
312
313         showDebugSettings =
314                 p.getBoolean(PREF_DEBUG_SETTINGS, showDebugSettings);
315         // Debug menu items have precidence if the menu is visible
316         if (showDebugSettings) {
317             boolean small_screen = p.getBoolean("small_screen",
318                     layoutAlgorithm ==
319                     WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
320             if (small_screen) {
321                 layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN;
322             } else {
323                 boolean normal_layout = p.getBoolean("normal_layout",
324                         layoutAlgorithm == WebSettings.LayoutAlgorithm.NORMAL);
325                 if (normal_layout) {
326                     layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL;
327                 } else {
328                     layoutAlgorithm =
329                             WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
330                 }
331             }
332             useWideViewPort = p.getBoolean("wide_viewport", useWideViewPort);
333             tracing = p.getBoolean("enable_tracing", tracing);
334             lightTouch = p.getBoolean("enable_light_touch", lightTouch);
335             navDump = p.getBoolean("enable_nav_dump", navDump);
336             userAgent = Integer.parseInt(p.getString("user_agent", "0"));
337         }
338         // JS flags is loaded from DB even if showDebugSettings is false,
339         // so that it can be set once and be effective all the time.
340         jsFlags = p.getString("js_engine_flags", "");
341
342         // Read the setting for showing/hiding the JS Console always so that should the
343         // user enable debug settings, we already know if we should show the console.
344         // The user will never see the console unless they navigate to about:debug,
345         // regardless of the setting we read here. This setting is only used after debug
346         // is enabled.
347         showConsole = p.getBoolean("javascript_console", showConsole);
348         mTabControl.getBrowserActivity().setShouldShowErrorConsole(
349                 showDebugSettings && showConsole);
350
351         // HTML5 API flags
352         appCacheEnabled = p.getBoolean("enable_appcache", appCacheEnabled);
353         databaseEnabled = p.getBoolean("enable_database", databaseEnabled);
354         domStorageEnabled = p.getBoolean("enable_domstorage", domStorageEnabled);
355         geolocationEnabled = p.getBoolean("enable_geolocation", geolocationEnabled);
356         workersEnabled = p.getBoolean("enable_workers", workersEnabled);
357
358         update();
359     }
360
361     public String getHomePage() {
362         return homeUrl;
363     }
364
365     public String getJsFlags() {
366         return jsFlags;
367     }
368
369     public WebStorageSizeManager getWebStorageSizeManager() {
370         return webStorageSizeManager;
371     }
372
373     public void setHomePage(Context context, String url) {
374         Editor ed = PreferenceManager.
375                 getDefaultSharedPreferences(context).edit();
376         ed.putString(PREF_HOMEPAGE, url);
377         ed.commit();
378         homeUrl = url;
379     }
380
381     public boolean isLoginInitialized() {
382         return loginInitialized;
383     }
384
385     public void setLoginInitialized(Context context) {
386         loginInitialized = true;
387         Editor ed = PreferenceManager.
388                 getDefaultSharedPreferences(context).edit();
389         ed.putBoolean("login_initialized", loginInitialized);
390         ed.commit();
391     }
392
393     public WebSettings.TextSize getTextSize() {
394         return textSize;
395     }
396
397     public WebSettings.ZoomDensity getDefaultZoom() {
398         return zoomDensity;
399     }
400
401     public boolean openInBackground() {
402         return openInBackground;
403     }
404
405     public boolean showSecurityWarnings() {
406         return showSecurityWarnings;
407     }
408
409     public boolean isTracing() {
410         return tracing;
411     }
412
413     public boolean isLightTouch() {
414         return lightTouch;
415     }
416
417     public boolean isNavDump() {
418         return navDump;
419     }
420
421     public boolean showDebugSettings() {
422         return showDebugSettings;
423     }
424
425     public void toggleDebugSettings() {
426         showDebugSettings = !showDebugSettings;
427         navDump = showDebugSettings;
428         update();
429     }
430
431     /**
432      * Add a WebSettings object to the list of observers that will be updated
433      * when update() is called.
434      *
435      * @param s A WebSettings object that is strictly tied to the life of a
436      *            WebView.
437      */
438     public Observer addObserver(WebSettings s) {
439         Observer old = mWebSettingsToObservers.get(s);
440         if (old != null) {
441             super.deleteObserver(old);
442         }
443         Observer o = new Observer(s);
444         mWebSettingsToObservers.put(s, o);
445         super.addObserver(o);
446         return o;
447     }
448
449     /**
450      * Delete the given WebSettings observer from the list of observers.
451      * @param s The WebSettings object to be deleted.
452      */
453     public void deleteObserver(WebSettings s) {
454         Observer o = mWebSettingsToObservers.get(s);
455         if (o != null) {
456             mWebSettingsToObservers.remove(s);
457             super.deleteObserver(o);
458         }
459     }
460
461     /*
462      * Package level method for obtaining a single app instance of the
463      * BrowserSettings.
464      */
465     /*package*/ static BrowserSettings getInstance() {
466         if (sSingleton == null ) {
467             sSingleton = new BrowserSettings();
468         }
469         return sSingleton;
470     }
471
472     /*
473      * Package level method for associating the BrowserSettings with TabControl
474      */
475     /* package */void setTabControl(TabControl tabControl) {
476         mTabControl = tabControl;
477     }
478
479     /*
480      * Update all the observers of the object.
481      */
482     /*package*/ void update() {
483         setChanged();
484         notifyObservers();
485     }
486
487     /*package*/ void clearCache(Context context) {
488         WebIconDatabase.getInstance().removeAllIcons();
489         if (mTabControl != null) {
490             WebView current = mTabControl.getCurrentWebView();
491             if (current != null) {
492                 current.clearCache(true);
493             }
494         }
495     }
496
497     /*package*/ void clearCookies(Context context) {
498         CookieManager.getInstance().removeAllCookie();
499     }
500
501     /* package */void clearHistory(Context context) {
502         ContentResolver resolver = context.getContentResolver();
503         Browser.clearHistory(resolver);
504         Browser.clearSearches(resolver);
505     }
506
507     /* package */ void clearFormData(Context context) {
508         WebViewDatabase.getInstance(context).clearFormData();
509         if (mTabControl != null) {
510             mTabControl.getCurrentTopWebView().clearFormData();
511         }
512     }
513
514     /*package*/ void clearPasswords(Context context) {
515         WebViewDatabase db = WebViewDatabase.getInstance(context);
516         db.clearUsernamePassword();
517         db.clearHttpAuthUsernamePassword();
518     }
519
520     private void maybeDisableWebsiteSettings(Context context) {
521         PreferenceActivity activity = (PreferenceActivity) context;
522         final PreferenceScreen screen = (PreferenceScreen)
523             activity.findPreference(BrowserSettings.PREF_WEBSITE_SETTINGS);
524         screen.setEnabled(false);
525         WebStorage.getInstance().getOrigins(new ValueCallback<Map>() {
526             public void onReceiveValue(Map webStorageOrigins) {
527                 if ((webStorageOrigins != null) && !webStorageOrigins.isEmpty()) {
528                     screen.setEnabled(true);
529                 }
530             }
531         });
532
533         GeolocationPermissions.getInstance().getOrigins(new ValueCallback<Set>() {
534             public void onReceiveValue(Set geolocationOrigins) {
535                 if ((geolocationOrigins != null) && !geolocationOrigins.isEmpty()) {
536                     screen.setEnabled(true);
537                 }
538             }
539         });
540     }
541
542     /*package*/ void clearDatabases(Context context) {
543         WebStorage.getInstance().deleteAllData();
544         maybeDisableWebsiteSettings(context);
545     }
546
547     /*package*/ void clearLocationAccess(Context context) {
548         GeolocationPermissions.getInstance().clearAll();
549         maybeDisableWebsiteSettings(context);
550     }
551
552     /*package*/ void resetDefaultPreferences(Context ctx) {
553         SharedPreferences p =
554             PreferenceManager.getDefaultSharedPreferences(ctx);
555         p.edit().clear().commit();
556         PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences,
557                 true);
558         // reset homeUrl
559         setHomePage(ctx, getFactoryResetHomeUrl(ctx));
560         // reset appcache max size
561         appCacheMaxSize = webStorageSizeManager.getAppCacheMaxSize();
562     }
563
564     private String getFactoryResetHomeUrl(Context context) {
565         String url = context.getResources().getString(R.string.homepage_base);
566         if (url.indexOf("{CID}") != -1) {
567             url = url.replace("{CID}", Partner.getString(context
568                     .getContentResolver(), Partner.CLIENT_ID, "android-google"));
569         }
570         return url;
571     }
572
573     // Private constructor that does nothing.
574     private BrowserSettings() {
575     }
576 }