1 2 /* 3 * Copyright (C) 2007 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.browser; 19 20 import com.android.browser.search.SearchEngine; 21 import com.android.browser.search.SearchEngines; 22 23 import android.app.ActivityManager; 24 import android.content.ComponentName; 25 import android.content.ContentResolver; 26 import android.content.ContentUris; 27 import android.content.ContentValues; 28 import android.content.Context; 29 import android.content.pm.ActivityInfo; 30 import android.content.pm.PackageManager; 31 import android.content.SharedPreferences; 32 import android.content.SharedPreferences.Editor; 33 import android.database.ContentObserver; 34 import android.database.Cursor; 35 import android.net.Uri; 36 import android.os.AsyncTask; 37 import android.os.Handler; 38 import android.preference.PreferenceActivity; 39 import android.preference.PreferenceScreen; 40 import android.provider.Browser.BookmarkColumns; 41 import android.provider.Settings; 42 import android.util.Log; 43 import android.webkit.CookieManager; 44 import android.webkit.GeolocationPermissions; 45 import android.webkit.ValueCallback; 46 import android.webkit.WebView; 47 import android.webkit.WebViewDatabase; 48 import android.webkit.WebIconDatabase; 49 import android.webkit.WebSettings; 50 import android.webkit.WebStorage; 51 import android.preference.PreferenceManager; 52 import android.provider.Browser; 53 54 import java.util.HashMap; 55 import java.util.Map; 56 import java.util.Set; 57 import 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 */ 72 class BrowserSettings extends Observable { 73 74 // Private variables for settings 75 // NOTE: these defaults need to be kept in sync with the XML 76 // until the performance of PreferenceManager.setDefaultValues() 77 // is improved. 78 // Note: boolean variables are set inside reset function. 79 private boolean loadsImagesAutomatically; 80 private boolean javaScriptEnabled; 81 private WebSettings.PluginState pluginState; 82 private boolean javaScriptCanOpenWindowsAutomatically; 83 private boolean showSecurityWarnings; 84 private boolean rememberPasswords; 85 private boolean saveFormData; 86 private boolean openInBackground; 87 private String defaultTextEncodingName; 88 private String homeUrl = ""; 89 private SearchEngine searchEngine; 90 private boolean autoFitPage; 91 private boolean landscapeOnly; 92 private boolean loadsPageInOverviewMode; 93 private boolean showDebugSettings; 94 // HTML5 API flags 95 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 100 // 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() 104 private String geolocationDatabasePath; // default value set in loadFromDb() 105 private WebStorageSizeManager webStorageSizeManager; 106 107 private String jsFlags = ""; 108 109 private final static String TAG = "BrowserSettings"; 110 111 // 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; 119 120 // 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 124 // 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; 131 private static WebSettings.ZoomDensity zoomDensity = 132 WebSettings.ZoomDensity.MEDIUM; 133 private static int pageCacheCapacity; 134 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"; 140 public final static String PREF_SEARCH_ENGINE = "search_engine"; 141 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"; 148 public final static String PREF_WEBSITE_SETTINGS = "website_settings"; 149 public final static String PREF_TEXT_SIZE = "text_size"; 150 public final static String PREF_DEFAULT_ZOOM = "default_zoom"; 151 public final static String PREF_DEFAULT_TEXT_ENCODING = 152 "default_text_encoding"; 153 public final static String PREF_CLEAR_GEOLOCATION_ACCESS = 154 "privacy_clear_geolocation_access"; 155 156 private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " + 157 "U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.16 (KHTML, " + 158 "like Gecko) Version/5.0 Safari/533.16"; 159 160 private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " + 161 "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"; 171 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 176 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 181 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 Observer(WebSettings w)199 Observer(WebSettings w) { 200 mSettings = w; 201 } 202 update(Observable o, Object arg)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); 215 } else if (b.userAgent == 3) { 216 s.setUserAgentString(IPAD_USERAGENT); 217 } else if (b.userAgent == 4) { 218 s.setUserAgentString(FROYO_USERAGENT); 219 } 220 s.setUseWideViewPort(b.useWideViewPort); 221 s.setLoadsImagesAutomatically(b.loadsImagesAutomatically); 222 s.setJavaScriptEnabled(b.javaScriptEnabled); 223 s.setPluginState(b.pluginState); 224 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); 233 s.setDefaultZoom(b.zoomDensity); 234 s.setLightTouchEnabled(b.lightTouch); 235 s.setSaveFormData(b.saveFormData); 236 s.setSavePassword(b.rememberPasswords); 237 s.setLoadWithOverviewMode(b.loadsPageInOverviewMode); 238 s.setPageCacheCapacity(pageCacheCapacity); 239 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); 244 // disable content url access 245 s.setAllowContentAccess(false); 246 247 // HTML5 API flags 248 s.setAppCacheEnabled(b.appCacheEnabled); 249 s.setDatabaseEnabled(b.databaseEnabled); 250 s.setDomStorageEnabled(b.domStorageEnabled); 251 s.setWorkersEnabled(b.workersEnabled); // This only affects V8. 252 s.setGeolocationEnabled(b.geolocationEnabled); 253 254 // HTML5 configuration parameters. 255 s.setAppCacheMaxSize(b.appCacheMaxSize); 256 s.setAppCachePath(b.appCachePath); 257 s.setDatabasePath(b.databasePath); 258 s.setGeolocationDatabasePath(b.geolocationDatabasePath); 259 260 b.updateTabControlSettings(); 261 } 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 */ loadFromDb(final Context ctx)273 public void loadFromDb(final Context ctx) { 274 SharedPreferences p = 275 PreferenceManager.getDefaultSharedPreferences(ctx); 276 // Set the default value for the Application Caches path. 277 appCachePath = ctx.getDir("appcache", 0).getPath(); 278 // Determine the maximum size of the application cache. 279 webStorageSizeManager = new WebStorageSizeManager( 280 ctx, 281 new WebStorageSizeManager.StatFsDiskInfo(appCachePath), 282 new WebStorageSizeManager.WebKitAppCacheInfo(appCachePath)); 283 appCacheMaxSize = webStorageSizeManager.getAppCacheMaxSize(); 284 // Set the default value for the Database path. 285 databasePath = ctx.getDir("databases", 0).getPath(); 286 // Set the default value for the Geolocation database path. 287 geolocationDatabasePath = ctx.getDir("geolocation", 0).getPath(); 288 289 if (p.getString(PREF_HOMEPAGE, "") == "") { 290 // No home page preferences is set, set it to default. 291 setHomePage(ctx, getFactoryResetHomeUrl(ctx)); 292 } 293 294 // 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) { 300 pageCacheCapacity = 5; 301 } else { 302 pageCacheCapacity = 1; 303 } 304 305 // Load the defaults from the xml 306 // This call is TOO SLOW, need to manually keep the defaults 307 // in sync 308 //PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences); 309 syncSharedPreferences(ctx, p); 310 } 311 syncSharedPreferences(Context ctx, SharedPreferences p)312 /* package */ void syncSharedPreferences(Context ctx, SharedPreferences p) { 313 314 homeUrl = 315 p.getString(PREF_HOMEPAGE, homeUrl); 316 String searchEngineName = p.getString(PREF_SEARCH_ENGINE, 317 SearchEngine.GOOGLE); 318 if (searchEngine == null || !searchEngine.getName().equals(searchEngineName)) { 319 if (searchEngine != null) { 320 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 } 328 searchEngine.close(); 329 } 330 searchEngine = SearchEngines.get(ctx, searchEngineName); 331 } 332 Log.i(TAG, "Selected search engine: " + searchEngine); 333 334 loadsImagesAutomatically = p.getBoolean("load_images", 335 loadsImagesAutomatically); 336 javaScriptEnabled = p.getBoolean("enable_javascript", 337 javaScriptEnabled); 338 pluginState = WebSettings.PluginState.valueOf( 339 p.getString("plugin_state", pluginState.name())); 340 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); 353 textSize = WebSettings.TextSize.valueOf( 354 p.getString(PREF_TEXT_SIZE, textSize.name())); 355 zoomDensity = WebSettings.ZoomDensity.valueOf( 356 p.getString(PREF_DEFAULT_ZOOM, zoomDensity.name())); 357 autoFitPage = p.getBoolean("autofit_pages", autoFitPage); 358 loadsPageInOverviewMode = p.getBoolean("load_page", 359 loadsPageInOverviewMode); 360 boolean landscapeOnlyTemp = 361 p.getBoolean("landscape_only", landscapeOnly); 362 if (landscapeOnlyTemp != landscapeOnly) { 363 landscapeOnly = landscapeOnlyTemp; 364 } 365 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); 398 userAgent = Integer.parseInt(p.getString("user_agent", "0")); 399 } 400 // 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", ""); 403 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); 410 411 // HTML5 API flags 412 appCacheEnabled = p.getBoolean("enable_appcache", appCacheEnabled); 413 databaseEnabled = p.getBoolean("enable_database", databaseEnabled); 414 domStorageEnabled = p.getBoolean("enable_domstorage", domStorageEnabled); 415 geolocationEnabled = p.getBoolean("enable_geolocation", geolocationEnabled); 416 workersEnabled = p.getBoolean("enable_workers", workersEnabled); 417 418 update(); 419 } 420 getHomePage()421 public String getHomePage() { 422 return homeUrl; 423 } 424 getSearchEngine()425 public SearchEngine getSearchEngine() { 426 return searchEngine; 427 } 428 getJsFlags()429 public String getJsFlags() { 430 return jsFlags; 431 } 432 getWebStorageSizeManager()433 public WebStorageSizeManager getWebStorageSizeManager() { 434 return webStorageSizeManager; 435 } 436 setHomePage(Context context, String url)437 public void setHomePage(Context context, String url) { 438 Editor ed = PreferenceManager. 439 getDefaultSharedPreferences(context).edit(); 440 ed.putString(PREF_HOMEPAGE, url); 441 ed.apply(); 442 homeUrl = url; 443 } 444 getTextSize()445 public WebSettings.TextSize getTextSize() { 446 return textSize; 447 } 448 getDefaultZoom()449 public WebSettings.ZoomDensity getDefaultZoom() { 450 return zoomDensity; 451 } 452 openInBackground()453 public boolean openInBackground() { 454 return openInBackground; 455 } 456 showSecurityWarnings()457 public boolean showSecurityWarnings() { 458 return showSecurityWarnings; 459 } 460 isTracing()461 public boolean isTracing() { 462 return tracing; 463 } 464 isLightTouch()465 public boolean isLightTouch() { 466 return lightTouch; 467 } 468 isNavDump()469 public boolean isNavDump() { 470 return navDump; 471 } 472 showDebugSettings()473 public boolean showDebugSettings() { 474 return showDebugSettings; 475 } 476 toggleDebugSettings()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 */ addObserver(WebSettings s)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 */ deleteObserver(WebSettings s)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 */ getInstance()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 */ setTabControl(TabControl tabControl)527 /* package */void setTabControl(TabControl tabControl) { 528 mTabControl = tabControl; 529 updateTabControlSettings(); 530 } 531 532 /* 533 * Update all the observers of the object. 534 */ update()535 /*package*/ void update() { 536 setChanged(); 537 notifyObservers(); 538 } 539 clearCache(Context context)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 clearCookies(Context context)550 /*package*/ void clearCookies(Context context) { 551 CookieManager.getInstance().removeAllCookie(); 552 } 553 clearHistory(Context context)554 /* package */void clearHistory(Context context) { 555 ContentResolver resolver = context.getContentResolver(); 556 Browser.clearHistory(resolver); 557 Browser.clearSearches(resolver); 558 } 559 clearFormData(Context context)560 /* package */ void clearFormData(Context context) { 561 WebViewDatabase.getInstance(context).clearFormData(); 562 if (mTabControl != null) { 563 WebView currentTopView = mTabControl.getCurrentTopWebView(); 564 if (currentTopView != null) { 565 currentTopView.clearFormData(); 566 } 567 } 568 } 569 clearPasswords(Context context)570 /*package*/ void clearPasswords(Context context) { 571 WebViewDatabase db = WebViewDatabase.getInstance(context); 572 db.clearUsernamePassword(); 573 db.clearHttpAuthUsernamePassword(); 574 } 575 updateTabControlSettings()576 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 maybeDisableWebsiteSettings(Context context)585 private void maybeDisableWebsiteSettings(Context context) { 586 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 598 GeolocationPermissions.getInstance().getOrigins(new ValueCallback<Set<String> >() { 599 public void onReceiveValue(Set<String> geolocationOrigins) { 600 if ((geolocationOrigins != null) && !geolocationOrigins.isEmpty()) { 601 screen.setEnabled(true); 602 } 603 } 604 }); 605 } 606 clearDatabases(Context context)607 /*package*/ void clearDatabases(Context context) { 608 WebStorage.getInstance().deleteAllData(); 609 maybeDisableWebsiteSettings(context); 610 } 611 clearLocationAccess(Context context)612 /*package*/ void clearLocationAccess(Context context) { 613 GeolocationPermissions.getInstance().clearAll(); 614 maybeDisableWebsiteSettings(context); 615 } 616 resetDefaultPreferences(Context ctx)617 /*package*/ void resetDefaultPreferences(Context ctx) { 618 reset(); 619 SharedPreferences p = 620 PreferenceManager.getDefaultSharedPreferences(ctx); 621 p.edit().clear().apply(); 622 PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences, 623 true); 624 // reset homeUrl 625 setHomePage(ctx, getFactoryResetHomeUrl(ctx)); 626 // reset appcache max size 627 appCacheMaxSize = webStorageSizeManager.getAppCacheMaxSize(); 628 } 629 getFactoryResetHomeUrl(Context context)630 private String getFactoryResetHomeUrl(Context context) { 631 String url = context.getResources().getString(R.string.homepage_base); 632 if (url.indexOf("{CID}") != -1) { 633 url = url.replace("{CID}", 634 BrowserProvider.getClientId(context.getContentResolver())); 635 } 636 return url; 637 } 638 639 // Private constructor that does nothing. BrowserSettings()640 private BrowserSettings() { 641 reset(); 642 } 643 reset()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; 651 pluginState = WebSettings.PluginState.ON; 652 javaScriptCanOpenWindowsAutomatically = false; 653 showSecurityWarnings = true; 654 rememberPasswords = true; 655 saveFormData = true; 656 openInBackground = false; 657 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 667 } 668 getRlzValue()669 /*package*/ String getRlzValue() { 670 return mRlzValue; 671 } 672 updateRlzValues(Context context)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 RlzUpdateTask(Context context)681 public RlzUpdateTask(Context context) { 682 this.context = context; 683 } 684 685 @Override doInBackground(Void...unused)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 updateHomePageRlzParameter(Context context)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 updateBookmarksRlzParameter(Context context)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 updateRlzParameter(String url)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 retrieveRlzValue(Context context)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 } 779 } 780