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 17 package com.android.browser; 18 19 import com.google.android.providers.GoogleSettings.Partner; 20 21 import android.content.ContentResolver; 22 import android.content.Context; 23 import android.content.SharedPreferences; 24 import android.content.SharedPreferences.Editor; 25 import android.webkit.CookieManager; 26 import android.webkit.WebView; 27 import android.webkit.WebViewDatabase; 28 import android.webkit.WebIconDatabase; 29 import android.webkit.WebSettings; 30 import android.preference.PreferenceManager; 31 import android.provider.Browser; 32 33 import java.util.HashMap; 34 import java.util.Observable; 35 36 /* 37 * Package level class for storing various WebView and Browser settings. To use 38 * this class: 39 * BrowserSettings s = BrowserSettings.getInstance(); 40 * s.addObserver(webView.getSettings()); 41 * s.loadFromDb(context); // Only needed on app startup 42 * s.javaScriptEnabled = true; 43 * ... // set any other settings 44 * s.update(); // this will update all the observers 45 * 46 * To remove an observer: 47 * s.deleteObserver(webView.getSettings()); 48 */ 49 class BrowserSettings extends Observable { 50 51 // Public variables for settings 52 // NOTE: these defaults need to be kept in sync with the XML 53 // until the performance of PreferenceManager.setDefaultValues() 54 // is improved. 55 private boolean loadsImagesAutomatically = true; 56 private boolean javaScriptEnabled = true; 57 private boolean pluginsEnabled = true; 58 private String pluginsPath; // default value set in loadFromDb(). 59 private boolean javaScriptCanOpenWindowsAutomatically = false; 60 private boolean showSecurityWarnings = true; 61 private boolean rememberPasswords = true; 62 private boolean saveFormData = true; 63 private boolean openInBackground = false; 64 private String defaultTextEncodingName; 65 private String homeUrl = ""; 66 private boolean loginInitialized = false; 67 private boolean autoFitPage = true; 68 private boolean showDebugSettings = false; 69 70 // Development settings 71 public WebSettings.LayoutAlgorithm layoutAlgorithm = 72 WebSettings.LayoutAlgorithm.NARROW_COLUMNS; 73 private boolean useWideViewPort = true; 74 private int userAgent = 0; 75 private boolean tracing = false; 76 private boolean lightTouch = false; 77 private boolean navDump = false; 78 // Browser only settings 79 private boolean doFlick = false; 80 81 // Private preconfigured values 82 private static int minimumFontSize = 8; 83 private static int minimumLogicalFontSize = 8; 84 private static int defaultFontSize = 16; 85 private static int defaultFixedFontSize = 13; 86 private static WebSettings.TextSize textSize = 87 WebSettings.TextSize.NORMAL; 88 private static WebSettings.ZoomDensity zoomDensity = 89 WebSettings.ZoomDensity.MEDIUM; 90 91 // Preference keys that are used outside this class 92 public final static String PREF_CLEAR_CACHE = "privacy_clear_cache"; 93 public final static String PREF_CLEAR_COOKIES = "privacy_clear_cookies"; 94 public final static String PREF_CLEAR_HISTORY = "privacy_clear_history"; 95 public final static String PREF_HOMEPAGE = "homepage"; 96 public final static String PREF_CLEAR_FORM_DATA = 97 "privacy_clear_form_data"; 98 public final static String PREF_CLEAR_PASSWORDS = 99 "privacy_clear_passwords"; 100 public final static String PREF_EXTRAS_RESET_DEFAULTS = 101 "reset_default_preferences"; 102 public final static String PREF_DEBUG_SETTINGS = "debug_menu"; 103 public final static String PREF_GEARS_SETTINGS = "gears_settings"; 104 public final static String PREF_TEXT_SIZE = "text_size"; 105 public final static String PREF_DEFAULT_ZOOM = "default_zoom"; 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 Observer(WebSettings w)139 Observer(WebSettings w) { 140 mSettings = w; 141 } 142 update(Observable o, Object arg)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.setDefaultZoom(b.zoomDensity); 171 s.setLightTouchEnabled(b.lightTouch); 172 s.setSaveFormData(b.saveFormData); 173 s.setSavePassword(b.rememberPasswords); 174 175 // WebView inside Browser doesn't want initial focus to be set. 176 s.setNeedInitialFocus(false); 177 // Browser supports multiple windows 178 s.setSupportMultipleWindows(true); 179 // Turn off file access 180 s.setAllowFileAccess(false); 181 } 182 } 183 184 /** 185 * Load settings from the browser app's database. 186 * NOTE: Strings used for the preferences must match those specified 187 * in the browser_preferences.xml 188 * @param ctx A Context object used to query the browser's settings 189 * database. If the database exists, the saved settings will be 190 * stored in this BrowserSettings object. This will update all 191 * observers of this object. 192 */ loadFromDb(Context ctx)193 public void loadFromDb(Context ctx) { 194 SharedPreferences p = 195 PreferenceManager.getDefaultSharedPreferences(ctx); 196 197 // Set the default value for the plugins path to the application's 198 // local directory. 199 pluginsPath = ctx.getDir("plugins", 0).getPath(); 200 201 homeUrl = getFactoryResetHomeUrl(ctx); 202 203 // Load the defaults from the xml 204 // This call is TOO SLOW, need to manually keep the defaults 205 // in sync 206 //PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences); 207 syncSharedPreferences(p); 208 } 209 syncSharedPreferences(SharedPreferences p)210 /* package */ void syncSharedPreferences(SharedPreferences p) { 211 212 homeUrl = 213 p.getString(PREF_HOMEPAGE, homeUrl); 214 215 loadsImagesAutomatically = p.getBoolean("load_images", 216 loadsImagesAutomatically); 217 javaScriptEnabled = p.getBoolean("enable_javascript", 218 javaScriptEnabled); 219 pluginsEnabled = p.getBoolean("enable_plugins", 220 pluginsEnabled); 221 pluginsPath = p.getString("plugins_path", pluginsPath); 222 javaScriptCanOpenWindowsAutomatically = !p.getBoolean( 223 "block_popup_windows", 224 !javaScriptCanOpenWindowsAutomatically); 225 showSecurityWarnings = p.getBoolean("show_security_warnings", 226 showSecurityWarnings); 227 rememberPasswords = p.getBoolean("remember_passwords", 228 rememberPasswords); 229 saveFormData = p.getBoolean("save_formdata", 230 saveFormData); 231 boolean accept_cookies = p.getBoolean("accept_cookies", 232 CookieManager.getInstance().acceptCookie()); 233 CookieManager.getInstance().setAcceptCookie(accept_cookies); 234 openInBackground = p.getBoolean("open_in_background", openInBackground); 235 loginInitialized = p.getBoolean("login_initialized", loginInitialized); 236 textSize = WebSettings.TextSize.valueOf( 237 p.getString(PREF_TEXT_SIZE, textSize.name())); 238 zoomDensity = WebSettings.ZoomDensity.valueOf( 239 p.getString(PREF_DEFAULT_ZOOM, zoomDensity.name())); 240 autoFitPage = p.getBoolean("autofit_pages", autoFitPage); 241 useWideViewPort = true; // use wide view port for either setting 242 if (autoFitPage) { 243 layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS; 244 } else { 245 layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL; 246 } 247 defaultTextEncodingName = 248 p.getString(PREF_DEFAULT_TEXT_ENCODING, 249 defaultTextEncodingName); 250 251 showDebugSettings = 252 p.getBoolean(PREF_DEBUG_SETTINGS, showDebugSettings); 253 // Debug menu items have precidence if the menu is visible 254 if (showDebugSettings) { 255 boolean small_screen = p.getBoolean("small_screen", 256 layoutAlgorithm == 257 WebSettings.LayoutAlgorithm.SINGLE_COLUMN); 258 if (small_screen) { 259 layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN; 260 } else { 261 boolean normal_layout = p.getBoolean("normal_layout", 262 layoutAlgorithm == WebSettings.LayoutAlgorithm.NORMAL); 263 if (normal_layout) { 264 layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL; 265 } else { 266 layoutAlgorithm = 267 WebSettings.LayoutAlgorithm.NARROW_COLUMNS; 268 } 269 } 270 useWideViewPort = p.getBoolean("wide_viewport", useWideViewPort); 271 tracing = p.getBoolean("enable_tracing", tracing); 272 lightTouch = p.getBoolean("enable_light_touch", lightTouch); 273 navDump = p.getBoolean("enable_nav_dump", navDump); 274 doFlick = p.getBoolean("enable_flick", doFlick); 275 userAgent = Integer.parseInt(p.getString("user_agent", "0")); 276 } 277 update(); 278 } 279 getPluginsPath()280 public String getPluginsPath() { 281 return pluginsPath; 282 } 283 getHomePage()284 public String getHomePage() { 285 return homeUrl; 286 } 287 setHomePage(Context context, String url)288 public void setHomePage(Context context, String url) { 289 Editor ed = PreferenceManager. 290 getDefaultSharedPreferences(context).edit(); 291 ed.putString(PREF_HOMEPAGE, url); 292 ed.commit(); 293 homeUrl = url; 294 } 295 isLoginInitialized()296 public boolean isLoginInitialized() { 297 return loginInitialized; 298 } 299 setLoginInitialized(Context context)300 public void setLoginInitialized(Context context) { 301 loginInitialized = true; 302 Editor ed = PreferenceManager. 303 getDefaultSharedPreferences(context).edit(); 304 ed.putBoolean("login_initialized", loginInitialized); 305 ed.commit(); 306 } 307 getTextSize()308 public WebSettings.TextSize getTextSize() { 309 return textSize; 310 } 311 getDefaultZoom()312 public WebSettings.ZoomDensity getDefaultZoom() { 313 return zoomDensity; 314 } 315 openInBackground()316 public boolean openInBackground() { 317 return openInBackground; 318 } 319 showSecurityWarnings()320 public boolean showSecurityWarnings() { 321 return showSecurityWarnings; 322 } 323 isTracing()324 public boolean isTracing() { 325 return tracing; 326 } 327 isLightTouch()328 public boolean isLightTouch() { 329 return lightTouch; 330 } 331 isNavDump()332 public boolean isNavDump() { 333 return navDump; 334 } 335 doFlick()336 public boolean doFlick() { 337 return doFlick; 338 } 339 showDebugSettings()340 public boolean showDebugSettings() { 341 return showDebugSettings; 342 } 343 toggleDebugSettings()344 public void toggleDebugSettings() { 345 showDebugSettings = !showDebugSettings; 346 navDump = showDebugSettings; 347 update(); 348 } 349 350 /** 351 * Add a WebSettings object to the list of observers that will be updated 352 * when update() is called. 353 * 354 * @param s A WebSettings object that is strictly tied to the life of a 355 * WebView. 356 */ addObserver(WebSettings s)357 public Observer addObserver(WebSettings s) { 358 Observer old = mWebSettingsToObservers.get(s); 359 if (old != null) { 360 super.deleteObserver(old); 361 } 362 Observer o = new Observer(s); 363 mWebSettingsToObservers.put(s, o); 364 super.addObserver(o); 365 return o; 366 } 367 368 /** 369 * Delete the given WebSettings observer from the list of observers. 370 * @param s The WebSettings object to be deleted. 371 */ deleteObserver(WebSettings s)372 public void deleteObserver(WebSettings s) { 373 Observer o = mWebSettingsToObservers.get(s); 374 if (o != null) { 375 mWebSettingsToObservers.remove(s); 376 super.deleteObserver(o); 377 } 378 } 379 380 /* 381 * Package level method for obtaining a single app instance of the 382 * BrowserSettings. 383 */ getInstance()384 /*package*/ static BrowserSettings getInstance() { 385 if (sSingleton == null ) { 386 sSingleton = new BrowserSettings(); 387 } 388 return sSingleton; 389 } 390 391 /* 392 * Package level method for associating the BrowserSettings with TabControl 393 */ setTabControl(TabControl tabControl)394 /* package */void setTabControl(TabControl tabControl) { 395 mTabControl = tabControl; 396 } 397 398 /* 399 * Update all the observers of the object. 400 */ update()401 /*package*/ void update() { 402 setChanged(); 403 notifyObservers(); 404 } 405 clearCache(Context context)406 /*package*/ void clearCache(Context context) { 407 WebIconDatabase.getInstance().removeAllIcons(); 408 if (mTabControl != null) { 409 WebView current = mTabControl.getCurrentWebView(); 410 if (current != null) { 411 current.clearCache(true); 412 } 413 } 414 } 415 clearCookies(Context context)416 /*package*/ void clearCookies(Context context) { 417 CookieManager.getInstance().removeAllCookie(); 418 } 419 clearHistory(Context context)420 /* package */void clearHistory(Context context) { 421 ContentResolver resolver = context.getContentResolver(); 422 Browser.clearHistory(resolver); 423 Browser.clearSearches(resolver); 424 } 425 clearFormData(Context context)426 /* package */ void clearFormData(Context context) { 427 WebViewDatabase.getInstance(context).clearFormData(); 428 if (mTabControl != null) { 429 mTabControl.getCurrentTopWebView().clearFormData(); 430 } 431 } 432 clearPasswords(Context context)433 /*package*/ void clearPasswords(Context context) { 434 WebViewDatabase db = WebViewDatabase.getInstance(context); 435 db.clearUsernamePassword(); 436 db.clearHttpAuthUsernamePassword(); 437 } 438 resetDefaultPreferences(Context context)439 /*package*/ void resetDefaultPreferences(Context context) { 440 SharedPreferences p = 441 PreferenceManager.getDefaultSharedPreferences(context); 442 p.edit().clear().commit(); 443 PreferenceManager.setDefaultValues(context, R.xml.browser_preferences, 444 true); 445 // reset homeUrl 446 setHomePage(context, getFactoryResetHomeUrl(context)); 447 } 448 getFactoryResetHomeUrl(Context context)449 private String getFactoryResetHomeUrl(Context context) { 450 String url = context.getResources().getString(R.string.homepage_base); 451 if (url.indexOf("{CID}") != -1) { 452 url = url.replace("{CID}", Partner.getString(context 453 .getContentResolver(), Partner.CLIENT_ID, "android-google")); 454 } 455 return url; 456 } 457 458 // Private constructor that does nothing. BrowserSettings()459 private BrowserSettings() { 460 } 461 } 462