1 /* 2 * Copyright (C) 2011 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 android.app.ActivityManager; 20 import android.content.ContentResolver; 21 import android.content.Context; 22 import android.content.SharedPreferences; 23 import android.content.SharedPreferences.Editor; 24 import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 25 import android.net.ConnectivityManager; 26 import android.net.NetworkInfo; 27 import android.os.Build; 28 import android.os.Message; 29 import android.preference.PreferenceManager; 30 import android.provider.Browser; 31 import android.provider.Settings; 32 import android.util.DisplayMetrics; 33 import android.webkit.CookieManager; 34 import android.webkit.GeolocationPermissions; 35 import android.webkit.WebIconDatabase; 36 import android.webkit.WebSettings; 37 import android.webkit.WebSettings.LayoutAlgorithm; 38 import android.webkit.WebSettings.PluginState; 39 import android.webkit.WebSettings.TextSize; 40 import android.webkit.WebSettings.ZoomDensity; 41 import android.webkit.WebSettingsClassic; 42 import android.webkit.WebSettingsClassic.AutoFillProfile; 43 import android.webkit.WebStorage; 44 import android.webkit.WebView; 45 import android.webkit.WebViewDatabase; 46 47 import com.android.browser.homepages.HomeProvider; 48 import com.android.browser.provider.BrowserProvider; 49 import com.android.browser.search.SearchEngine; 50 import com.android.browser.search.SearchEngines; 51 52 import java.lang.ref.WeakReference; 53 import java.util.Iterator; 54 import java.util.LinkedList; 55 import java.util.WeakHashMap; 56 57 /** 58 * Class for managing settings 59 */ 60 public class BrowserSettings implements OnSharedPreferenceChangeListener, 61 PreferenceKeys { 62 63 // TODO: Do something with this UserAgent stuff 64 private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (X11; " + 65 "Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) " + 66 "Chrome/11.0.696.34 Safari/534.24"; 67 68 private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " + 69 "CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 " + 70 "(KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7"; 71 72 private static final String IPAD_USERAGENT = "Mozilla/5.0 (iPad; U; " + 73 "CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 " + 74 "(KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10"; 75 76 private static final String FROYO_USERAGENT = "Mozilla/5.0 (Linux; U; " + 77 "Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 " + 78 "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"; 79 80 private static final String HONEYCOMB_USERAGENT = "Mozilla/5.0 (Linux; U; " + 81 "Android 3.1; en-us; Xoom Build/HMJ25) AppleWebKit/534.13 " + 82 "(KHTML, like Gecko) Version/4.0 Safari/534.13"; 83 84 private static final String USER_AGENTS[] = { null, 85 DESKTOP_USERAGENT, 86 IPHONE_USERAGENT, 87 IPAD_USERAGENT, 88 FROYO_USERAGENT, 89 HONEYCOMB_USERAGENT, 90 }; 91 92 // The minimum min font size 93 // Aka, the lower bounds for the min font size range 94 // which is 1:5..24 95 private static final int MIN_FONT_SIZE_OFFSET = 5; 96 // The initial value in the text zoom range 97 // This is what represents 100% in the SeekBarPreference range 98 private static final int TEXT_ZOOM_START_VAL = 10; 99 // The size of a single step in the text zoom range, in percent 100 private static final int TEXT_ZOOM_STEP = 5; 101 // The initial value in the double tap zoom range 102 // This is what represents 100% in the SeekBarPreference range 103 private static final int DOUBLE_TAP_ZOOM_START_VAL = 5; 104 // The size of a single step in the double tap zoom range, in percent 105 private static final int DOUBLE_TAP_ZOOM_STEP = 5; 106 107 private static BrowserSettings sInstance; 108 109 private Context mContext; 110 private SharedPreferences mPrefs; 111 private LinkedList<WeakReference<WebSettings>> mManagedSettings; 112 private Controller mController; 113 private WebStorageSizeManager mWebStorageSizeManager; 114 private AutofillHandler mAutofillHandler; 115 private WeakHashMap<WebSettings, String> mCustomUserAgents; 116 private static boolean sInitialized = false; 117 private boolean mNeedsSharedSync = true; 118 private float mFontSizeMult = 1.0f; 119 120 // Current state of network-dependent settings 121 private boolean mLinkPrefetchAllowed = true; 122 123 // Cached values 124 private int mPageCacheCapacity = 1; 125 private String mAppCachePath; 126 127 // Cached settings 128 private SearchEngine mSearchEngine; 129 130 private static String sFactoryResetUrl; 131 132 public static void initialize(final Context context) { 133 sInstance = new BrowserSettings(context); 134 } 135 136 public static BrowserSettings getInstance() { 137 return sInstance; 138 } 139 140 private BrowserSettings(Context context) { 141 mContext = context.getApplicationContext(); 142 mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext); 143 mAutofillHandler = new AutofillHandler(mContext); 144 mManagedSettings = new LinkedList<WeakReference<WebSettings>>(); 145 mCustomUserAgents = new WeakHashMap<WebSettings, String>(); 146 mAutofillHandler.asyncLoadFromDb(); 147 BackgroundHandler.execute(mSetup); 148 } 149 150 public void setController(Controller controller) { 151 mController = controller; 152 if (sInitialized) { 153 syncSharedSettings(); 154 } 155 } 156 157 public void startManagingSettings(WebSettings settings) { 158 159 if (mNeedsSharedSync) { 160 syncSharedSettings(); 161 } 162 163 synchronized (mManagedSettings) { 164 syncStaticSettings(settings); 165 syncSetting(settings); 166 mManagedSettings.add(new WeakReference<WebSettings>(settings)); 167 } 168 } 169 170 public void stopManagingSettings(WebSettings settings) { 171 Iterator<WeakReference<WebSettings>> iter = mManagedSettings.iterator(); 172 while (iter.hasNext()) { 173 WeakReference<WebSettings> ref = iter.next(); 174 if (ref.get() == settings) { 175 iter.remove(); 176 return; 177 } 178 } 179 } 180 181 private Runnable mSetup = new Runnable() { 182 183 @Override 184 public void run() { 185 DisplayMetrics metrics = mContext.getResources().getDisplayMetrics(); 186 mFontSizeMult = metrics.scaledDensity / metrics.density; 187 // the cost of one cached page is ~3M (measured using nytimes.com). For 188 // low end devices, we only cache one page. For high end devices, we try 189 // to cache more pages, currently choose 5. 190 if (ActivityManager.staticGetMemoryClass() > 16) { 191 mPageCacheCapacity = 5; 192 } 193 mWebStorageSizeManager = new WebStorageSizeManager(mContext, 194 new WebStorageSizeManager.StatFsDiskInfo(getAppCachePath()), 195 new WebStorageSizeManager.WebKitAppCacheInfo(getAppCachePath())); 196 // Workaround b/5254577 197 mPrefs.registerOnSharedPreferenceChangeListener(BrowserSettings.this); 198 if (Build.VERSION.CODENAME.equals("REL")) { 199 // This is a release build, always startup with debug disabled 200 setDebugEnabled(false); 201 } 202 if (mPrefs.contains(PREF_TEXT_SIZE)) { 203 /* 204 * Update from TextSize enum to zoom percent 205 * SMALLEST is 50% 206 * SMALLER is 75% 207 * NORMAL is 100% 208 * LARGER is 150% 209 * LARGEST is 200% 210 */ 211 switch (getTextSize()) { 212 case SMALLEST: 213 setTextZoom(50); 214 break; 215 case SMALLER: 216 setTextZoom(75); 217 break; 218 case LARGER: 219 setTextZoom(150); 220 break; 221 case LARGEST: 222 setTextZoom(200); 223 break; 224 } 225 mPrefs.edit().remove(PREF_TEXT_SIZE).apply(); 226 } 227 228 sFactoryResetUrl = mContext.getResources().getString(R.string.homepage_base); 229 if (sFactoryResetUrl.indexOf("{CID}") != -1) { 230 sFactoryResetUrl = sFactoryResetUrl.replace("{CID}", 231 BrowserProvider.getClientId(mContext.getContentResolver())); 232 } 233 234 synchronized (BrowserSettings.class) { 235 sInitialized = true; 236 BrowserSettings.class.notifyAll(); 237 } 238 } 239 }; 240 241 private static void requireInitialization() { 242 synchronized (BrowserSettings.class) { 243 while (!sInitialized) { 244 try { 245 BrowserSettings.class.wait(); 246 } catch (InterruptedException e) { 247 } 248 } 249 } 250 } 251 252 /** 253 * Syncs all the settings that have a Preference UI 254 */ 255 private void syncSetting(WebSettings settings) { 256 settings.setGeolocationEnabled(enableGeolocation()); 257 settings.setJavaScriptEnabled(enableJavascript()); 258 settings.setLightTouchEnabled(enableLightTouch()); 259 settings.setNavDump(enableNavDump()); 260 settings.setDefaultTextEncodingName(getDefaultTextEncoding()); 261 settings.setDefaultZoom(getDefaultZoom()); 262 settings.setMinimumFontSize(getMinimumFontSize()); 263 settings.setMinimumLogicalFontSize(getMinimumFontSize()); 264 settings.setPluginState(getPluginState()); 265 settings.setTextZoom(getTextZoom()); 266 settings.setLayoutAlgorithm(getLayoutAlgorithm()); 267 settings.setJavaScriptCanOpenWindowsAutomatically(!blockPopupWindows()); 268 settings.setLoadsImagesAutomatically(loadImages()); 269 settings.setLoadWithOverviewMode(loadPageInOverviewMode()); 270 settings.setSavePassword(rememberPasswords()); 271 settings.setSaveFormData(saveFormdata()); 272 settings.setUseWideViewPort(isWideViewport()); 273 274 String ua = mCustomUserAgents.get(settings); 275 if (ua != null) { 276 settings.setUserAgentString(ua); 277 } else { 278 settings.setUserAgentString(USER_AGENTS[getUserAgent()]); 279 } 280 281 if (!(settings instanceof WebSettingsClassic)) return; 282 283 WebSettingsClassic settingsClassic = (WebSettingsClassic) settings; 284 settingsClassic.setHardwareAccelSkiaEnabled(isSkiaHardwareAccelerated()); 285 settingsClassic.setShowVisualIndicator(enableVisualIndicator()); 286 settingsClassic.setForceUserScalable(forceEnableUserScalable()); 287 settingsClassic.setDoubleTapZoom(getDoubleTapZoom()); 288 settingsClassic.setAutoFillEnabled(isAutofillEnabled()); 289 settingsClassic.setAutoFillProfile(getAutoFillProfile()); 290 291 boolean useInverted = useInvertedRendering(); 292 settingsClassic.setProperty(WebViewProperties.gfxInvertedScreen, 293 useInverted ? "true" : "false"); 294 if (useInverted) { 295 settingsClassic.setProperty(WebViewProperties.gfxInvertedScreenContrast, 296 Float.toString(getInvertedContrast())); 297 } 298 299 if (isDebugEnabled()) { 300 settingsClassic.setProperty(WebViewProperties.gfxEnableCpuUploadPath, 301 enableCpuUploadPath() ? "true" : "false"); 302 } 303 304 settingsClassic.setLinkPrefetchEnabled(mLinkPrefetchAllowed); 305 } 306 307 /** 308 * Syncs all the settings that have no UI 309 * These cannot change, so we only need to set them once per WebSettings 310 */ 311 private void syncStaticSettings(WebSettings settings) { 312 settings.setDefaultFontSize(16); 313 settings.setDefaultFixedFontSize(13); 314 315 // WebView inside Browser doesn't want initial focus to be set. 316 settings.setNeedInitialFocus(false); 317 // Browser supports multiple windows 318 settings.setSupportMultipleWindows(true); 319 // enable smooth transition for better performance during panning or 320 // zooming 321 settings.setEnableSmoothTransition(true); 322 // disable content url access 323 settings.setAllowContentAccess(false); 324 325 // HTML5 API flags 326 settings.setAppCacheEnabled(true); 327 settings.setDatabaseEnabled(true); 328 settings.setDomStorageEnabled(true); 329 330 // HTML5 configuration parametersettings. 331 settings.setAppCacheMaxSize(getWebStorageSizeManager().getAppCacheMaxSize()); 332 settings.setAppCachePath(getAppCachePath()); 333 settings.setDatabasePath(mContext.getDir("databases", 0).getPath()); 334 settings.setGeolocationDatabasePath(mContext.getDir("geolocation", 0).getPath()); 335 // origin policy for file access 336 settings.setAllowUniversalAccessFromFileURLs(false); 337 settings.setAllowFileAccessFromFileURLs(false); 338 339 if (!(settings instanceof WebSettingsClassic)) return; 340 341 WebSettingsClassic settingsClassic = (WebSettingsClassic) settings; 342 settingsClassic.setPageCacheCapacity(getPageCacheCapacity()); 343 // WebView should be preserving the memory as much as possible. 344 // However, apps like browser wish to turn on the performance mode which 345 // would require more memory. 346 // TODO: We need to dynamically allocate/deallocate temporary memory for 347 // apps which are trying to use minimal memory. Currently, double 348 // buffering is always turned on, which is unnecessary. 349 settingsClassic.setProperty(WebViewProperties.gfxUseMinimalMemory, "false"); 350 settingsClassic.setWorkersEnabled(true); // This only affects V8. 351 } 352 353 private void syncSharedSettings() { 354 mNeedsSharedSync = false; 355 CookieManager.getInstance().setAcceptCookie(acceptCookies()); 356 if (mController != null) { 357 mController.setShouldShowErrorConsole(enableJavascriptConsole()); 358 } 359 } 360 361 private void syncManagedSettings() { 362 syncSharedSettings(); 363 synchronized (mManagedSettings) { 364 Iterator<WeakReference<WebSettings>> iter = mManagedSettings.iterator(); 365 while (iter.hasNext()) { 366 WeakReference<WebSettings> ref = iter.next(); 367 WebSettings settings = ref.get(); 368 if (settings == null) { 369 iter.remove(); 370 continue; 371 } 372 syncSetting(settings); 373 } 374 } 375 } 376 377 @Override 378 public void onSharedPreferenceChanged( 379 SharedPreferences sharedPreferences, String key) { 380 syncManagedSettings(); 381 if (PREF_SEARCH_ENGINE.equals(key)) { 382 updateSearchEngine(false); 383 } else if (PREF_FULLSCREEN.equals(key)) { 384 if (mController != null && mController.getUi() != null) { 385 mController.getUi().setFullscreen(useFullscreen()); 386 } 387 } else if (PREF_ENABLE_QUICK_CONTROLS.equals(key)) { 388 if (mController != null && mController.getUi() != null) { 389 mController.getUi().setUseQuickControls(sharedPreferences.getBoolean(key, false)); 390 } 391 } else if (PREF_LINK_PREFETCH.equals(key)) { 392 updateConnectionType(); 393 } 394 } 395 396 public static String getFactoryResetHomeUrl(Context context) { 397 requireInitialization(); 398 return sFactoryResetUrl; 399 } 400 401 public LayoutAlgorithm getLayoutAlgorithm() { 402 LayoutAlgorithm layoutAlgorithm = LayoutAlgorithm.NORMAL; 403 if (autofitPages()) { 404 layoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS; 405 } 406 if (isDebugEnabled()) { 407 if (isSmallScreen()) { 408 layoutAlgorithm = LayoutAlgorithm.SINGLE_COLUMN; 409 } else { 410 if (isNormalLayout()) { 411 layoutAlgorithm = LayoutAlgorithm.NORMAL; 412 } else { 413 layoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS; 414 } 415 } 416 } 417 return layoutAlgorithm; 418 } 419 420 public int getPageCacheCapacity() { 421 requireInitialization(); 422 return mPageCacheCapacity; 423 } 424 425 public WebStorageSizeManager getWebStorageSizeManager() { 426 requireInitialization(); 427 return mWebStorageSizeManager; 428 } 429 430 private String getAppCachePath() { 431 if (mAppCachePath == null) { 432 mAppCachePath = mContext.getDir("appcache", 0).getPath(); 433 } 434 return mAppCachePath; 435 } 436 437 private void updateSearchEngine(boolean force) { 438 String searchEngineName = getSearchEngineName(); 439 if (force || mSearchEngine == null || 440 !mSearchEngine.getName().equals(searchEngineName)) { 441 mSearchEngine = SearchEngines.get(mContext, searchEngineName); 442 } 443 } 444 445 public SearchEngine getSearchEngine() { 446 if (mSearchEngine == null) { 447 updateSearchEngine(false); 448 } 449 return mSearchEngine; 450 } 451 452 public boolean isDebugEnabled() { 453 requireInitialization(); 454 return mPrefs.getBoolean(PREF_DEBUG_MENU, false); 455 } 456 457 public void setDebugEnabled(boolean value) { 458 Editor edit = mPrefs.edit(); 459 edit.putBoolean(PREF_DEBUG_MENU, value); 460 if (!value) { 461 // Reset to "safe" value 462 edit.putBoolean(PREF_ENABLE_HARDWARE_ACCEL_SKIA, false); 463 } 464 edit.apply(); 465 } 466 467 public void clearCache() { 468 WebIconDatabase.getInstance().removeAllIcons(); 469 if (mController != null) { 470 WebView current = mController.getCurrentWebView(); 471 if (current != null) { 472 current.clearCache(true); 473 } 474 } 475 } 476 477 public void clearCookies() { 478 CookieManager.getInstance().removeAllCookie(); 479 } 480 481 public void clearHistory() { 482 ContentResolver resolver = mContext.getContentResolver(); 483 Browser.clearHistory(resolver); 484 Browser.clearSearches(resolver); 485 } 486 487 public void clearFormData() { 488 WebViewDatabase.getInstance(mContext).clearFormData(); 489 if (mController!= null) { 490 WebView currentTopView = mController.getCurrentTopWebView(); 491 if (currentTopView != null) { 492 currentTopView.clearFormData(); 493 } 494 } 495 } 496 497 public void clearPasswords() { 498 WebViewDatabase db = WebViewDatabase.getInstance(mContext); 499 db.clearUsernamePassword(); 500 db.clearHttpAuthUsernamePassword(); 501 } 502 503 public void clearDatabases() { 504 WebStorage.getInstance().deleteAllData(); 505 } 506 507 public void clearLocationAccess() { 508 GeolocationPermissions.getInstance().clearAll(); 509 } 510 511 public void resetDefaultPreferences() { 512 // Preserve autologin setting 513 long gal = mPrefs.getLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, -1); 514 mPrefs.edit() 515 .clear() 516 .putLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, gal) 517 .apply(); 518 resetCachedValues(); 519 syncManagedSettings(); 520 } 521 522 private void resetCachedValues() { 523 updateSearchEngine(false); 524 } 525 526 public AutoFillProfile getAutoFillProfile() { 527 return mAutofillHandler.getAutoFillProfile(); 528 } 529 530 public void setAutoFillProfile(AutoFillProfile profile, Message msg) { 531 mAutofillHandler.setAutoFillProfile(profile, msg); 532 // Auto-fill will reuse the same profile ID when making edits to the profile, 533 // so we need to force a settings sync (otherwise the SharedPreferences 534 // manager will optimise out the call to onSharedPreferenceChanged(), as 535 // it thinks nothing has changed). 536 syncManagedSettings(); 537 } 538 539 public void toggleDebugSettings() { 540 setDebugEnabled(!isDebugEnabled()); 541 } 542 543 public boolean hasDesktopUseragent(WebView view) { 544 return view != null && mCustomUserAgents.get(view.getSettings()) != null; 545 } 546 547 public void toggleDesktopUseragent(WebView view) { 548 if (view == null) { 549 return; 550 } 551 WebSettings settings = view.getSettings(); 552 if (mCustomUserAgents.get(settings) != null) { 553 mCustomUserAgents.remove(settings); 554 settings.setUserAgentString(USER_AGENTS[getUserAgent()]); 555 } else { 556 mCustomUserAgents.put(settings, DESKTOP_USERAGENT); 557 settings.setUserAgentString(DESKTOP_USERAGENT); 558 } 559 } 560 561 public static int getAdjustedMinimumFontSize(int rawValue) { 562 rawValue++; // Preference starts at 0, min font at 1 563 if (rawValue > 1) { 564 rawValue += (MIN_FONT_SIZE_OFFSET - 2); 565 } 566 return rawValue; 567 } 568 569 public int getAdjustedTextZoom(int rawValue) { 570 rawValue = (rawValue - TEXT_ZOOM_START_VAL) * TEXT_ZOOM_STEP; 571 return (int) ((rawValue + 100) * mFontSizeMult); 572 } 573 574 static int getRawTextZoom(int percent) { 575 return (percent - 100) / TEXT_ZOOM_STEP + TEXT_ZOOM_START_VAL; 576 } 577 578 public int getAdjustedDoubleTapZoom(int rawValue) { 579 rawValue = (rawValue - DOUBLE_TAP_ZOOM_START_VAL) * DOUBLE_TAP_ZOOM_STEP; 580 return (int) ((rawValue + 100) * mFontSizeMult); 581 } 582 583 static int getRawDoubleTapZoom(int percent) { 584 return (percent - 100) / DOUBLE_TAP_ZOOM_STEP + DOUBLE_TAP_ZOOM_START_VAL; 585 } 586 587 public SharedPreferences getPreferences() { 588 return mPrefs; 589 } 590 591 // update connectivity-dependent options 592 public void updateConnectionType() { 593 ConnectivityManager cm = (ConnectivityManager) 594 mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 595 String linkPrefetchPreference = getLinkPrefetchEnabled(); 596 boolean linkPrefetchAllowed = linkPrefetchPreference. 597 equals(getLinkPrefetchAlwaysPreferenceString(mContext)); 598 NetworkInfo ni = cm.getActiveNetworkInfo(); 599 if (ni != null) { 600 switch (ni.getType()) { 601 case ConnectivityManager.TYPE_WIFI: 602 case ConnectivityManager.TYPE_ETHERNET: 603 case ConnectivityManager.TYPE_BLUETOOTH: 604 linkPrefetchAllowed |= linkPrefetchPreference. 605 equals(getLinkPrefetchOnWifiOnlyPreferenceString(mContext)); 606 break; 607 case ConnectivityManager.TYPE_MOBILE: 608 case ConnectivityManager.TYPE_MOBILE_DUN: 609 case ConnectivityManager.TYPE_MOBILE_MMS: 610 case ConnectivityManager.TYPE_MOBILE_SUPL: 611 case ConnectivityManager.TYPE_WIMAX: 612 default: 613 break; 614 } 615 } 616 if (mLinkPrefetchAllowed != linkPrefetchAllowed) { 617 mLinkPrefetchAllowed = linkPrefetchAllowed; 618 syncManagedSettings(); 619 } 620 } 621 622 // ----------------------------- 623 // getter/setters for accessibility_preferences.xml 624 // ----------------------------- 625 626 @Deprecated 627 private TextSize getTextSize() { 628 String textSize = mPrefs.getString(PREF_TEXT_SIZE, "NORMAL"); 629 return TextSize.valueOf(textSize); 630 } 631 632 public int getMinimumFontSize() { 633 int minFont = mPrefs.getInt(PREF_MIN_FONT_SIZE, 0); 634 return getAdjustedMinimumFontSize(minFont); 635 } 636 637 public boolean forceEnableUserScalable() { 638 return mPrefs.getBoolean(PREF_FORCE_USERSCALABLE, false); 639 } 640 641 public int getTextZoom() { 642 requireInitialization(); 643 int textZoom = mPrefs.getInt(PREF_TEXT_ZOOM, 10); 644 return getAdjustedTextZoom(textZoom); 645 } 646 647 public void setTextZoom(int percent) { 648 mPrefs.edit().putInt(PREF_TEXT_ZOOM, getRawTextZoom(percent)).apply(); 649 } 650 651 public int getDoubleTapZoom() { 652 requireInitialization(); 653 int doubleTapZoom = mPrefs.getInt(PREF_DOUBLE_TAP_ZOOM, 5); 654 return getAdjustedDoubleTapZoom(doubleTapZoom); 655 } 656 657 public void setDoubleTapZoom(int percent) { 658 mPrefs.edit().putInt(PREF_DOUBLE_TAP_ZOOM, getRawDoubleTapZoom(percent)).apply(); 659 } 660 661 // ----------------------------- 662 // getter/setters for advanced_preferences.xml 663 // ----------------------------- 664 665 public String getSearchEngineName() { 666 return mPrefs.getString(PREF_SEARCH_ENGINE, SearchEngine.GOOGLE); 667 } 668 669 public boolean allowAppTabs() { 670 return mPrefs.getBoolean(PREF_ALLOW_APP_TABS, false); 671 } 672 673 public boolean openInBackground() { 674 return mPrefs.getBoolean(PREF_OPEN_IN_BACKGROUND, false); 675 } 676 677 public boolean enableJavascript() { 678 return mPrefs.getBoolean(PREF_ENABLE_JAVASCRIPT, true); 679 } 680 681 // TODO: Cache 682 public PluginState getPluginState() { 683 String state = mPrefs.getString(PREF_PLUGIN_STATE, "ON"); 684 return PluginState.valueOf(state); 685 } 686 687 // TODO: Cache 688 public ZoomDensity getDefaultZoom() { 689 String zoom = mPrefs.getString(PREF_DEFAULT_ZOOM, "MEDIUM"); 690 return ZoomDensity.valueOf(zoom); 691 } 692 693 public boolean loadPageInOverviewMode() { 694 return mPrefs.getBoolean(PREF_LOAD_PAGE, true); 695 } 696 697 public boolean autofitPages() { 698 return mPrefs.getBoolean(PREF_AUTOFIT_PAGES, true); 699 } 700 701 public boolean blockPopupWindows() { 702 return mPrefs.getBoolean(PREF_BLOCK_POPUP_WINDOWS, true); 703 } 704 705 public boolean loadImages() { 706 return mPrefs.getBoolean(PREF_LOAD_IMAGES, true); 707 } 708 709 public String getDefaultTextEncoding() { 710 return mPrefs.getString(PREF_DEFAULT_TEXT_ENCODING, null); 711 } 712 713 // ----------------------------- 714 // getter/setters for general_preferences.xml 715 // ----------------------------- 716 717 public String getHomePage() { 718 return mPrefs.getString(PREF_HOMEPAGE, getFactoryResetHomeUrl(mContext)); 719 } 720 721 public void setHomePage(String value) { 722 mPrefs.edit().putString(PREF_HOMEPAGE, value).apply(); 723 } 724 725 public boolean isAutofillEnabled() { 726 return mPrefs.getBoolean(PREF_AUTOFILL_ENABLED, true); 727 } 728 729 public void setAutofillEnabled(boolean value) { 730 mPrefs.edit().putBoolean(PREF_AUTOFILL_ENABLED, value).apply(); 731 } 732 733 // ----------------------------- 734 // getter/setters for debug_preferences.xml 735 // ----------------------------- 736 737 public boolean isHardwareAccelerated() { 738 if (!isDebugEnabled()) { 739 return true; 740 } 741 return mPrefs.getBoolean(PREF_ENABLE_HARDWARE_ACCEL, true); 742 } 743 744 public boolean isSkiaHardwareAccelerated() { 745 if (!isDebugEnabled()) { 746 return false; 747 } 748 return mPrefs.getBoolean(PREF_ENABLE_HARDWARE_ACCEL_SKIA, false); 749 } 750 751 public int getUserAgent() { 752 if (!isDebugEnabled()) { 753 return 0; 754 } 755 return Integer.parseInt(mPrefs.getString(PREF_USER_AGENT, "0")); 756 } 757 758 // ----------------------------- 759 // getter/setters for hidden_debug_preferences.xml 760 // ----------------------------- 761 762 public boolean enableVisualIndicator() { 763 if (!isDebugEnabled()) { 764 return false; 765 } 766 return mPrefs.getBoolean(PREF_ENABLE_VISUAL_INDICATOR, false); 767 } 768 769 public boolean enableCpuUploadPath() { 770 if (!isDebugEnabled()) { 771 return false; 772 } 773 return mPrefs.getBoolean(PREF_ENABLE_CPU_UPLOAD_PATH, false); 774 } 775 776 public boolean enableJavascriptConsole() { 777 if (!isDebugEnabled()) { 778 return false; 779 } 780 return mPrefs.getBoolean(PREF_JAVASCRIPT_CONSOLE, true); 781 } 782 783 public boolean isSmallScreen() { 784 if (!isDebugEnabled()) { 785 return false; 786 } 787 return mPrefs.getBoolean(PREF_SMALL_SCREEN, false); 788 } 789 790 public boolean isWideViewport() { 791 if (!isDebugEnabled()) { 792 return true; 793 } 794 return mPrefs.getBoolean(PREF_WIDE_VIEWPORT, true); 795 } 796 797 public boolean isNormalLayout() { 798 if (!isDebugEnabled()) { 799 return false; 800 } 801 return mPrefs.getBoolean(PREF_NORMAL_LAYOUT, false); 802 } 803 804 public boolean isTracing() { 805 if (!isDebugEnabled()) { 806 return false; 807 } 808 return mPrefs.getBoolean(PREF_ENABLE_TRACING, false); 809 } 810 811 public boolean enableLightTouch() { 812 if (!isDebugEnabled()) { 813 return false; 814 } 815 return mPrefs.getBoolean(PREF_ENABLE_LIGHT_TOUCH, false); 816 } 817 818 public boolean enableNavDump() { 819 if (!isDebugEnabled()) { 820 return false; 821 } 822 return mPrefs.getBoolean(PREF_ENABLE_NAV_DUMP, false); 823 } 824 825 public String getJsEngineFlags() { 826 if (!isDebugEnabled()) { 827 return ""; 828 } 829 return mPrefs.getString(PREF_JS_ENGINE_FLAGS, ""); 830 } 831 832 // ----------------------------- 833 // getter/setters for lab_preferences.xml 834 // ----------------------------- 835 836 public boolean useQuickControls() { 837 return mPrefs.getBoolean(PREF_ENABLE_QUICK_CONTROLS, false); 838 } 839 840 public boolean useMostVisitedHomepage() { 841 return HomeProvider.MOST_VISITED.equals(getHomePage()); 842 } 843 844 public boolean useFullscreen() { 845 return mPrefs.getBoolean(PREF_FULLSCREEN, false); 846 } 847 848 public boolean useInvertedRendering() { 849 return mPrefs.getBoolean(PREF_INVERTED, false); 850 } 851 852 public float getInvertedContrast() { 853 return 1 + (mPrefs.getInt(PREF_INVERTED_CONTRAST, 0) / 10f); 854 } 855 856 // ----------------------------- 857 // getter/setters for privacy_security_preferences.xml 858 // ----------------------------- 859 860 public boolean showSecurityWarnings() { 861 return mPrefs.getBoolean(PREF_SHOW_SECURITY_WARNINGS, true); 862 } 863 864 public boolean acceptCookies() { 865 return mPrefs.getBoolean(PREF_ACCEPT_COOKIES, true); 866 } 867 868 public boolean saveFormdata() { 869 return mPrefs.getBoolean(PREF_SAVE_FORMDATA, true); 870 } 871 872 public boolean enableGeolocation() { 873 return mPrefs.getBoolean(PREF_ENABLE_GEOLOCATION, true); 874 } 875 876 public boolean rememberPasswords() { 877 return mPrefs.getBoolean(PREF_REMEMBER_PASSWORDS, true); 878 } 879 880 // ----------------------------- 881 // getter/setters for bandwidth_preferences.xml 882 // ----------------------------- 883 884 public static String getPreloadOnWifiOnlyPreferenceString(Context context) { 885 return context.getResources().getString(R.string.pref_data_preload_value_wifi_only); 886 } 887 888 public static String getPreloadAlwaysPreferenceString(Context context) { 889 return context.getResources().getString(R.string.pref_data_preload_value_always); 890 } 891 892 private static final String DEAULT_PRELOAD_SECURE_SETTING_KEY = 893 "browser_default_preload_setting"; 894 895 public String getDefaultPreloadSetting() { 896 String preload = Settings.Secure.getString(mContext.getContentResolver(), 897 DEAULT_PRELOAD_SECURE_SETTING_KEY); 898 if (preload == null) { 899 preload = mContext.getResources().getString(R.string.pref_data_preload_default_value); 900 } 901 return preload; 902 } 903 904 public String getPreloadEnabled() { 905 return mPrefs.getString(PREF_DATA_PRELOAD, getDefaultPreloadSetting()); 906 } 907 908 public static String getLinkPrefetchOnWifiOnlyPreferenceString(Context context) { 909 return context.getResources().getString(R.string.pref_link_prefetch_value_wifi_only); 910 } 911 912 public static String getLinkPrefetchAlwaysPreferenceString(Context context) { 913 return context.getResources().getString(R.string.pref_link_prefetch_value_always); 914 } 915 916 private static final String DEFAULT_LINK_PREFETCH_SECURE_SETTING_KEY = 917 "browser_default_link_prefetch_setting"; 918 919 public String getDefaultLinkPrefetchSetting() { 920 String preload = Settings.Secure.getString(mContext.getContentResolver(), 921 DEFAULT_LINK_PREFETCH_SECURE_SETTING_KEY); 922 if (preload == null) { 923 preload = mContext.getResources().getString(R.string.pref_link_prefetch_default_value); 924 } 925 return preload; 926 } 927 928 public String getLinkPrefetchEnabled() { 929 return mPrefs.getString(PREF_LINK_PREFETCH, getDefaultLinkPrefetchSetting()); 930 } 931 932 // ----------------------------- 933 // getter/setters for browser recovery 934 // ----------------------------- 935 /** 936 * The last time browser was started. 937 * @return The last browser start time as System.currentTimeMillis. This 938 * can be 0 if this is the first time or the last tab was closed. 939 */ 940 public long getLastRecovered() { 941 return mPrefs.getLong(KEY_LAST_RECOVERED, 0); 942 } 943 944 /** 945 * Sets the last browser start time. 946 * @param time The last time as System.currentTimeMillis that the browser 947 * was started. This should be set to 0 if the last tab is closed. 948 */ 949 public void setLastRecovered(long time) { 950 mPrefs.edit() 951 .putLong(KEY_LAST_RECOVERED, time) 952 .apply(); 953 } 954 955 /** 956 * Used to determine whether or not the previous browser run crashed. Once 957 * the previous state has been determined, the value will be set to false 958 * until a pause is received. 959 * @return true if the last browser run was paused or false if it crashed. 960 */ 961 public boolean wasLastRunPaused() { 962 return mPrefs.getBoolean(KEY_LAST_RUN_PAUSED, false); 963 } 964 965 /** 966 * Sets whether or not the last run was a pause or crash. 967 * @param isPaused Set to true When a pause is received or false after 968 * resuming. 969 */ 970 public void setLastRunPaused(boolean isPaused) { 971 mPrefs.edit() 972 .putBoolean(KEY_LAST_RUN_PAUSED, isPaused) 973 .apply(); 974 } 975 } 976