WebSettings.java revision 178db41234abd08925fea9a4dc5180218f7da737
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.webkit; 18 19import android.content.Context; 20import android.content.SharedPreferences; 21import android.content.pm.PackageManager; 22import android.os.Build; 23import android.os.Handler; 24import android.os.Message; 25import android.util.EventLog; 26import java.lang.SecurityException; 27import java.util.Locale; 28 29/** 30 * Manages settings state for a WebView. When a WebView is first created, it 31 * obtains a set of default settings. These default settings will be returned 32 * from any getter call. A WebSettings object obtained from 33 * WebView.getSettings() is tied to the life of the WebView. If a WebView has 34 * been destroyed, any method call on WebSettings will throw an 35 * IllegalStateException. 36 */ 37public class WebSettings { 38 /** 39 * Enum for controlling the layout of html. 40 * NORMAL means no rendering changes. 41 * SINGLE_COLUMN moves all content into one column that is the width of the 42 * view. 43 * NARROW_COLUMNS makes all columns no wider than the screen if possible. 44 */ 45 // XXX: These must match LayoutAlgorithm in Settings.h in WebCore. 46 public enum LayoutAlgorithm { 47 NORMAL, 48 SINGLE_COLUMN, 49 NARROW_COLUMNS 50 } 51 52 /** 53 * Enum for specifying the text size. 54 * SMALLEST is 50% 55 * SMALLER is 75% 56 * NORMAL is 100% 57 * LARGER is 150% 58 * LARGEST is 200% 59 */ 60 public enum TextSize { 61 SMALLEST(50), 62 SMALLER(75), 63 NORMAL(100), 64 LARGER(150), 65 LARGEST(200); 66 TextSize(int size) { 67 value = size; 68 } 69 int value; 70 } 71 72 /** 73 * Enum for specifying the WebView's desired density. 74 * FAR makes 100% looking like in 240dpi 75 * MEDIUM makes 100% looking like in 160dpi 76 * CLOSE makes 100% looking like in 120dpi 77 */ 78 public enum ZoomDensity { 79 FAR(150), // 240dpi 80 MEDIUM(100), // 160dpi 81 CLOSE(75); // 120dpi 82 ZoomDensity(int size) { 83 value = size; 84 } 85 int value; 86 } 87 88 /** 89 * Default cache usage pattern Use with {@link #setCacheMode}. 90 */ 91 public static final int LOAD_DEFAULT = -1; 92 93 /** 94 * Normal cache usage pattern Use with {@link #setCacheMode}. 95 */ 96 public static final int LOAD_NORMAL = 0; 97 98 /** 99 * Use cache if content is there, even if expired (eg, history nav) 100 * If it is not in the cache, load from network. 101 * Use with {@link #setCacheMode}. 102 */ 103 public static final int LOAD_CACHE_ELSE_NETWORK = 1; 104 105 /** 106 * Don't use the cache, load from network 107 * Use with {@link #setCacheMode}. 108 */ 109 public static final int LOAD_NO_CACHE = 2; 110 111 /** 112 * Don't use the network, load from cache only. 113 * Use with {@link #setCacheMode}. 114 */ 115 public static final int LOAD_CACHE_ONLY = 3; 116 117 public enum RenderPriority { 118 NORMAL, 119 HIGH, 120 LOW 121 } 122 123 /** 124 * The plugin state effects how plugins are treated on a page. ON means 125 * that any object will be loaded even if a plugin does not exist to handle 126 * the content. ON_DEMAND means that if there is a plugin installed that 127 * can handle the content, a placeholder is shown until the user clicks on 128 * the placeholder. Once clicked, the plugin will be enabled on the page. 129 * OFF means that all plugins will be turned off and any fallback content 130 * will be used. 131 */ 132 public enum PluginState { 133 ON, 134 ON_DEMAND, 135 OFF 136 } 137 138 // WebView associated with this WebSettings. 139 private WebView mWebView; 140 // BrowserFrame used to access the native frame pointer. 141 private BrowserFrame mBrowserFrame; 142 // Flag to prevent multiple SYNC messages at one time. 143 private boolean mSyncPending = false; 144 // Custom handler that queues messages until the WebCore thread is active. 145 private final EventHandler mEventHandler; 146 147 // Private settings so we don't have to go into native code to 148 // retrieve the values. After setXXX, postSync() needs to be called. 149 // 150 // The default values need to match those in WebSettings.cpp 151 // If the defaults change, please also update the JavaDocs so developers 152 // know what they are. 153 private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS; 154 private Context mContext; 155 private TextSize mTextSize = TextSize.NORMAL; 156 private String mStandardFontFamily = "sans-serif"; 157 private String mFixedFontFamily = "monospace"; 158 private String mSansSerifFontFamily = "sans-serif"; 159 private String mSerifFontFamily = "serif"; 160 private String mCursiveFontFamily = "cursive"; 161 private String mFantasyFontFamily = "fantasy"; 162 private String mDefaultTextEncoding; 163 private String mUserAgent; 164 private boolean mUseDefaultUserAgent; 165 private String mAcceptLanguage; 166 private int mMinimumFontSize = 8; 167 private int mMinimumLogicalFontSize = 8; 168 private int mDefaultFontSize = 16; 169 private int mDefaultFixedFontSize = 13; 170 private int mPageCacheCapacity = 0; 171 private boolean mLoadsImagesAutomatically = true; 172 private boolean mBlockNetworkImage = false; 173 private boolean mBlockNetworkLoads; 174 private boolean mJavaScriptEnabled = false; 175 private PluginState mPluginState = PluginState.OFF; 176 private boolean mJavaScriptCanOpenWindowsAutomatically = false; 177 private boolean mUseDoubleTree = false; 178 private boolean mUseWideViewport = false; 179 private boolean mSupportMultipleWindows = false; 180 private boolean mShrinksStandaloneImagesToFit = false; 181 // HTML5 API flags 182 private boolean mAppCacheEnabled = false; 183 private boolean mDatabaseEnabled = false; 184 private boolean mDomStorageEnabled = false; 185 private boolean mWorkersEnabled = false; // only affects V8. 186 private boolean mGeolocationEnabled = true; 187 // HTML5 configuration parameters 188 private long mAppCacheMaxSize = Long.MAX_VALUE; 189 private String mAppCachePath = ""; 190 private String mDatabasePath = ""; 191 // The WebCore DatabaseTracker only allows the database path to be set 192 // once. Keep track of when the path has been set. 193 private boolean mDatabasePathHasBeenSet = false; 194 private String mGeolocationDatabasePath = ""; 195 // Don't need to synchronize the get/set methods as they 196 // are basic types, also none of these values are used in 197 // native WebCore code. 198 private ZoomDensity mDefaultZoom = ZoomDensity.MEDIUM; 199 private RenderPriority mRenderPriority = RenderPriority.NORMAL; 200 private int mOverrideCacheMode = LOAD_DEFAULT; 201 private boolean mSaveFormData = true; 202 private boolean mSavePassword = true; 203 private boolean mLightTouchEnabled = false; 204 private boolean mNeedInitialFocus = true; 205 private boolean mNavDump = false; 206 private boolean mSupportZoom = true; 207 private boolean mBuiltInZoomControls = false; 208 private boolean mAllowFileAccess = true; 209 private boolean mLoadWithOverviewMode = false; 210 211 // private WebSettings, not accessible by the host activity 212 static private int mDoubleTapToastCount = 3; 213 214 private static final String PREF_FILE = "WebViewSettings"; 215 private static final String DOUBLE_TAP_TOAST_COUNT = "double_tap_toast_count"; 216 217 // Class to handle messages before WebCore is ready. 218 private class EventHandler { 219 // Message id for syncing 220 static final int SYNC = 0; 221 // Message id for setting priority 222 static final int PRIORITY = 1; 223 // Message id for writing double-tap toast count 224 static final int SET_DOUBLE_TAP_TOAST_COUNT = 2; 225 // Actual WebCore thread handler 226 private Handler mHandler; 227 228 private synchronized void createHandler() { 229 // as mRenderPriority can be set before thread is running, sync up 230 setRenderPriority(); 231 232 // create a new handler 233 mHandler = new Handler() { 234 @Override 235 public void handleMessage(Message msg) { 236 switch (msg.what) { 237 case SYNC: 238 synchronized (WebSettings.this) { 239 if (mBrowserFrame.mNativeFrame != 0) { 240 nativeSync(mBrowserFrame.mNativeFrame); 241 } 242 mSyncPending = false; 243 } 244 break; 245 246 case PRIORITY: { 247 setRenderPriority(); 248 break; 249 } 250 251 case SET_DOUBLE_TAP_TOAST_COUNT: { 252 SharedPreferences.Editor editor = mContext 253 .getSharedPreferences(PREF_FILE, 254 Context.MODE_PRIVATE).edit(); 255 editor.putInt(DOUBLE_TAP_TOAST_COUNT, 256 mDoubleTapToastCount); 257 editor.commit(); 258 break; 259 } 260 } 261 } 262 }; 263 } 264 265 private void setRenderPriority() { 266 synchronized (WebSettings.this) { 267 if (mRenderPriority == RenderPriority.NORMAL) { 268 android.os.Process.setThreadPriority( 269 android.os.Process.THREAD_PRIORITY_DEFAULT); 270 } else if (mRenderPriority == RenderPriority.HIGH) { 271 android.os.Process.setThreadPriority( 272 android.os.Process.THREAD_PRIORITY_FOREGROUND + 273 android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE); 274 } else if (mRenderPriority == RenderPriority.LOW) { 275 android.os.Process.setThreadPriority( 276 android.os.Process.THREAD_PRIORITY_BACKGROUND); 277 } 278 } 279 } 280 281 /** 282 * Send a message to the private queue or handler. 283 */ 284 private synchronized boolean sendMessage(Message msg) { 285 if (mHandler != null) { 286 mHandler.sendMessage(msg); 287 return true; 288 } else { 289 return false; 290 } 291 } 292 } 293 294 // User agent strings. 295 private static final String DESKTOP_USERAGENT = 296 "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us)" 297 + " AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0" 298 + " Safari/530.17"; 299 private static final String IPHONE_USERAGENT = 300 "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)" 301 + " AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0" 302 + " Mobile/7A341 Safari/528.16"; 303 private static Locale sLocale; 304 private static Object sLockForLocaleSettings; 305 306 /** 307 * Package constructor to prevent clients from creating a new settings 308 * instance. 309 */ 310 WebSettings(Context context, WebView webview) { 311 mEventHandler = new EventHandler(); 312 mContext = context; 313 mWebView = webview; 314 mDefaultTextEncoding = context.getString(com.android.internal. 315 R.string.default_text_encoding); 316 317 if (sLockForLocaleSettings == null) { 318 sLockForLocaleSettings = new Object(); 319 sLocale = Locale.getDefault(); 320 } 321 mAcceptLanguage = getCurrentAcceptLanguage(); 322 mUserAgent = getCurrentUserAgent(); 323 mUseDefaultUserAgent = true; 324 325 mBlockNetworkLoads = mContext.checkPermission( 326 "android.permission.INTERNET", android.os.Process.myPid(), 327 android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED; 328 } 329 330 private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US"; 331 332 /** 333 * Looks at sLocale and returns current AcceptLanguage String. 334 * @return Current AcceptLanguage String. 335 */ 336 private String getCurrentAcceptLanguage() { 337 Locale locale; 338 synchronized(sLockForLocaleSettings) { 339 locale = sLocale; 340 } 341 StringBuilder buffer = new StringBuilder(); 342 addLocaleToHttpAcceptLanguage(buffer, locale); 343 344 if (!Locale.US.equals(locale)) { 345 if (buffer.length() > 0) { 346 buffer.append(", "); 347 } 348 buffer.append(ACCEPT_LANG_FOR_US_LOCALE); 349 } 350 351 return buffer.toString(); 352 } 353 354 /** 355 * Convert obsolete language codes, including Hebrew/Indonesian/Yiddish, 356 * to new standard. 357 */ 358 private static String convertObsoleteLanguageCodeToNew(String langCode) { 359 if (langCode == null) { 360 return null; 361 } 362 if ("iw".equals(langCode)) { 363 // Hebrew 364 return "he"; 365 } else if ("in".equals(langCode)) { 366 // Indonesian 367 return "id"; 368 } else if ("ji".equals(langCode)) { 369 // Yiddish 370 return "yi"; 371 } 372 return langCode; 373 } 374 375 private static void addLocaleToHttpAcceptLanguage(StringBuilder builder, 376 Locale locale) { 377 String language = convertObsoleteLanguageCodeToNew(locale.getLanguage()); 378 if (language != null) { 379 builder.append(language); 380 String country = locale.getCountry(); 381 if (country != null) { 382 builder.append("-"); 383 builder.append(country); 384 } 385 } 386 } 387 388 /** 389 * Looks at sLocale and mContext and returns current UserAgent String. 390 * @return Current UserAgent String. 391 */ 392 private synchronized String getCurrentUserAgent() { 393 Locale locale; 394 synchronized(sLockForLocaleSettings) { 395 locale = sLocale; 396 } 397 StringBuffer buffer = new StringBuffer(); 398 // Add version 399 final String version = Build.VERSION.RELEASE; 400 if (version.length() > 0) { 401 buffer.append(version); 402 } else { 403 // default to "1.0" 404 buffer.append("1.0"); 405 } 406 buffer.append("; "); 407 final String language = locale.getLanguage(); 408 if (language != null) { 409 buffer.append(convertObsoleteLanguageCodeToNew(language)); 410 final String country = locale.getCountry(); 411 if (country != null) { 412 buffer.append("-"); 413 buffer.append(country.toLowerCase()); 414 } 415 } else { 416 // default to "en" 417 buffer.append("en"); 418 } 419 // add the model for the release build 420 if ("REL".equals(Build.VERSION.CODENAME)) { 421 final String model = Build.MODEL; 422 if (model.length() > 0) { 423 buffer.append("; "); 424 buffer.append(model); 425 } 426 } 427 final String id = Build.ID; 428 if (id.length() > 0) { 429 buffer.append(" Build/"); 430 buffer.append(id); 431 } 432 final String base = mContext.getResources().getText( 433 com.android.internal.R.string.web_user_agent).toString(); 434 return String.format(base, buffer); 435 } 436 437 /** 438 * Enables dumping the pages navigation cache to a text file. 439 */ 440 public void setNavDump(boolean enabled) { 441 mNavDump = enabled; 442 } 443 444 /** 445 * Returns true if dumping the navigation cache is enabled. 446 */ 447 public boolean getNavDump() { 448 return mNavDump; 449 } 450 451 /** 452 * If WebView only supports touch, a different navigation model will be 453 * applied. Otherwise, the navigation to support both touch and keyboard 454 * will be used. 455 * @hide 456 public void setSupportTouchOnly(boolean touchOnly) { 457 mSupportTounchOnly = touchOnly; 458 } 459 */ 460 461 boolean supportTouchOnly() { 462 // for debug only, use mLightTouchEnabled for mSupportTounchOnly 463 return mLightTouchEnabled; 464 } 465 466 /** 467 * Set whether the WebView supports zoom 468 */ 469 public void setSupportZoom(boolean support) { 470 mSupportZoom = support; 471 mWebView.updateMultiTouchSupport(mContext); 472 } 473 474 /** 475 * Returns whether the WebView supports zoom 476 */ 477 public boolean supportZoom() { 478 return mSupportZoom; 479 } 480 481 /** 482 * Sets whether the zoom mechanism built into WebView is used. 483 */ 484 public void setBuiltInZoomControls(boolean enabled) { 485 mBuiltInZoomControls = enabled; 486 mWebView.updateMultiTouchSupport(mContext); 487 } 488 489 /** 490 * Returns true if the zoom mechanism built into WebView is being used. 491 */ 492 public boolean getBuiltInZoomControls() { 493 return mBuiltInZoomControls; 494 } 495 496 /** 497 * Enable or disable file access within WebView. File access is enabled by 498 * default. 499 */ 500 public void setAllowFileAccess(boolean allow) { 501 mAllowFileAccess = allow; 502 } 503 504 /** 505 * Returns true if this WebView supports file access. 506 */ 507 public boolean getAllowFileAccess() { 508 return mAllowFileAccess; 509 } 510 511 /** 512 * Set whether the WebView loads a page with overview mode. 513 */ 514 public void setLoadWithOverviewMode(boolean overview) { 515 mLoadWithOverviewMode = overview; 516 } 517 518 /** 519 * Returns true if this WebView loads page with overview mode 520 */ 521 public boolean getLoadWithOverviewMode() { 522 return mLoadWithOverviewMode; 523 } 524 525 /** 526 * Store whether the WebView is saving form data. 527 */ 528 public void setSaveFormData(boolean save) { 529 mSaveFormData = save; 530 } 531 532 /** 533 * Return whether the WebView is saving form data. 534 */ 535 public boolean getSaveFormData() { 536 return mSaveFormData; 537 } 538 539 /** 540 * Store whether the WebView is saving password. 541 */ 542 public void setSavePassword(boolean save) { 543 mSavePassword = save; 544 } 545 546 /** 547 * Return whether the WebView is saving password. 548 */ 549 public boolean getSavePassword() { 550 return mSavePassword; 551 } 552 553 /** 554 * Set the text size of the page. 555 * @param t A TextSize value for increasing or decreasing the text. 556 * @see WebSettings.TextSize 557 */ 558 public synchronized void setTextSize(TextSize t) { 559 if (WebView.mLogEvent && mTextSize != t ) { 560 EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE, 561 mTextSize.value, t.value); 562 } 563 mTextSize = t; 564 postSync(); 565 } 566 567 /** 568 * Get the text size of the page. 569 * @return A TextSize enum value describing the text size. 570 * @see WebSettings.TextSize 571 */ 572 public synchronized TextSize getTextSize() { 573 return mTextSize; 574 } 575 576 /** 577 * Set the default zoom density of the page. This should be called from UI 578 * thread. 579 * @param zoom A ZoomDensity value 580 * @see WebSettings.ZoomDensity 581 */ 582 public void setDefaultZoom(ZoomDensity zoom) { 583 if (mDefaultZoom != zoom) { 584 mDefaultZoom = zoom; 585 mWebView.updateDefaultZoomDensity(zoom.value); 586 } 587 } 588 589 /** 590 * Get the default zoom density of the page. This should be called from UI 591 * thread. 592 * @return A ZoomDensity value 593 * @see WebSettings.ZoomDensity 594 */ 595 public ZoomDensity getDefaultZoom() { 596 return mDefaultZoom; 597 } 598 599 /** 600 * Enables using light touches to make a selection and activate mouseovers. 601 */ 602 public void setLightTouchEnabled(boolean enabled) { 603 mLightTouchEnabled = enabled; 604 } 605 606 /** 607 * Returns true if light touches are enabled. 608 */ 609 public boolean getLightTouchEnabled() { 610 return mLightTouchEnabled; 611 } 612 613 /** 614 * @deprecated This setting controlled a rendering optimization 615 * that is no longer present. Setting it now has no effect. 616 */ 617 @Deprecated 618 public synchronized void setUseDoubleTree(boolean use) { 619 return; 620 } 621 622 /** 623 * @deprecated This setting controlled a rendering optimization 624 * that is no longer present. Setting it now has no effect. 625 */ 626 @Deprecated 627 public synchronized boolean getUseDoubleTree() { 628 return false; 629 } 630 631 /** 632 * Tell the WebView about user-agent string. 633 * @param ua 0 if the WebView should use an Android user-agent string, 634 * 1 if the WebView should use a desktop user-agent string. 635 * 636 * @deprecated Please use setUserAgentString instead. 637 */ 638 @Deprecated 639 public synchronized void setUserAgent(int ua) { 640 String uaString = null; 641 if (ua == 1) { 642 if (DESKTOP_USERAGENT.equals(mUserAgent)) { 643 return; // do nothing 644 } else { 645 uaString = DESKTOP_USERAGENT; 646 } 647 } else if (ua == 2) { 648 if (IPHONE_USERAGENT.equals(mUserAgent)) { 649 return; // do nothing 650 } else { 651 uaString = IPHONE_USERAGENT; 652 } 653 } else if (ua != 0) { 654 return; // do nothing 655 } 656 setUserAgentString(uaString); 657 } 658 659 /** 660 * Return user-agent as int 661 * @return int 0 if the WebView is using an Android user-agent string. 662 * 1 if the WebView is using a desktop user-agent string. 663 * -1 if the WebView is using user defined user-agent string. 664 * 665 * @deprecated Please use getUserAgentString instead. 666 */ 667 @Deprecated 668 public synchronized int getUserAgent() { 669 if (DESKTOP_USERAGENT.equals(mUserAgent)) { 670 return 1; 671 } else if (IPHONE_USERAGENT.equals(mUserAgent)) { 672 return 2; 673 } else if (mUseDefaultUserAgent) { 674 return 0; 675 } 676 return -1; 677 } 678 679 /** 680 * Tell the WebView to use the wide viewport 681 */ 682 public synchronized void setUseWideViewPort(boolean use) { 683 if (mUseWideViewport != use) { 684 mUseWideViewport = use; 685 postSync(); 686 } 687 } 688 689 /** 690 * @return True if the WebView is using a wide viewport 691 */ 692 public synchronized boolean getUseWideViewPort() { 693 return mUseWideViewport; 694 } 695 696 /** 697 * Tell the WebView whether it supports multiple windows. TRUE means 698 * that {@link WebChromeClient#onCreateWindow(WebView, boolean, 699 * boolean, Message)} is implemented by the host application. 700 */ 701 public synchronized void setSupportMultipleWindows(boolean support) { 702 if (mSupportMultipleWindows != support) { 703 mSupportMultipleWindows = support; 704 postSync(); 705 } 706 } 707 708 /** 709 * @return True if the WebView is supporting multiple windows. This means 710 * that {@link WebChromeClient#onCreateWindow(WebView, boolean, 711 * boolean, Message)} is implemented by the host application. 712 */ 713 public synchronized boolean supportMultipleWindows() { 714 return mSupportMultipleWindows; 715 } 716 717 /** 718 * Set the underlying layout algorithm. This will cause a relayout of the 719 * WebView. 720 * @param l A LayoutAlgorithm enum specifying the algorithm to use. 721 * @see WebSettings.LayoutAlgorithm 722 */ 723 public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) { 724 // XXX: This will only be affective if libwebcore was built with 725 // ANDROID_LAYOUT defined. 726 if (mLayoutAlgorithm != l) { 727 mLayoutAlgorithm = l; 728 postSync(); 729 } 730 } 731 732 /** 733 * Return the current layout algorithm. The default is NARROW_COLUMNS. 734 * @return LayoutAlgorithm enum value describing the layout algorithm 735 * being used. 736 * @see WebSettings.LayoutAlgorithm 737 */ 738 public synchronized LayoutAlgorithm getLayoutAlgorithm() { 739 return mLayoutAlgorithm; 740 } 741 742 /** 743 * Set the standard font family name. 744 * @param font A font family name. 745 */ 746 public synchronized void setStandardFontFamily(String font) { 747 if (font != null && !font.equals(mStandardFontFamily)) { 748 mStandardFontFamily = font; 749 postSync(); 750 } 751 } 752 753 /** 754 * Get the standard font family name. The default is "sans-serif". 755 * @return The standard font family name as a string. 756 */ 757 public synchronized String getStandardFontFamily() { 758 return mStandardFontFamily; 759 } 760 761 /** 762 * Set the fixed font family name. 763 * @param font A font family name. 764 */ 765 public synchronized void setFixedFontFamily(String font) { 766 if (font != null && !font.equals(mFixedFontFamily)) { 767 mFixedFontFamily = font; 768 postSync(); 769 } 770 } 771 772 /** 773 * Get the fixed font family name. The default is "monospace". 774 * @return The fixed font family name as a string. 775 */ 776 public synchronized String getFixedFontFamily() { 777 return mFixedFontFamily; 778 } 779 780 /** 781 * Set the sans-serif font family name. 782 * @param font A font family name. 783 */ 784 public synchronized void setSansSerifFontFamily(String font) { 785 if (font != null && !font.equals(mSansSerifFontFamily)) { 786 mSansSerifFontFamily = font; 787 postSync(); 788 } 789 } 790 791 /** 792 * Get the sans-serif font family name. 793 * @return The sans-serif font family name as a string. 794 */ 795 public synchronized String getSansSerifFontFamily() { 796 return mSansSerifFontFamily; 797 } 798 799 /** 800 * Set the serif font family name. The default is "sans-serif". 801 * @param font A font family name. 802 */ 803 public synchronized void setSerifFontFamily(String font) { 804 if (font != null && !font.equals(mSerifFontFamily)) { 805 mSerifFontFamily = font; 806 postSync(); 807 } 808 } 809 810 /** 811 * Get the serif font family name. The default is "serif". 812 * @return The serif font family name as a string. 813 */ 814 public synchronized String getSerifFontFamily() { 815 return mSerifFontFamily; 816 } 817 818 /** 819 * Set the cursive font family name. 820 * @param font A font family name. 821 */ 822 public synchronized void setCursiveFontFamily(String font) { 823 if (font != null && !font.equals(mCursiveFontFamily)) { 824 mCursiveFontFamily = font; 825 postSync(); 826 } 827 } 828 829 /** 830 * Get the cursive font family name. The default is "cursive". 831 * @return The cursive font family name as a string. 832 */ 833 public synchronized String getCursiveFontFamily() { 834 return mCursiveFontFamily; 835 } 836 837 /** 838 * Set the fantasy font family name. 839 * @param font A font family name. 840 */ 841 public synchronized void setFantasyFontFamily(String font) { 842 if (font != null && !font.equals(mFantasyFontFamily)) { 843 mFantasyFontFamily = font; 844 postSync(); 845 } 846 } 847 848 /** 849 * Get the fantasy font family name. The default is "fantasy". 850 * @return The fantasy font family name as a string. 851 */ 852 public synchronized String getFantasyFontFamily() { 853 return mFantasyFontFamily; 854 } 855 856 /** 857 * Set the minimum font size. 858 * @param size A non-negative integer between 1 and 72. 859 * Any number outside the specified range will be pinned. 860 */ 861 public synchronized void setMinimumFontSize(int size) { 862 size = pin(size); 863 if (mMinimumFontSize != size) { 864 mMinimumFontSize = size; 865 postSync(); 866 } 867 } 868 869 /** 870 * Get the minimum font size. The default is 8. 871 * @return A non-negative integer between 1 and 72. 872 */ 873 public synchronized int getMinimumFontSize() { 874 return mMinimumFontSize; 875 } 876 877 /** 878 * Set the minimum logical font size. 879 * @param size A non-negative integer between 1 and 72. 880 * Any number outside the specified range will be pinned. 881 */ 882 public synchronized void setMinimumLogicalFontSize(int size) { 883 size = pin(size); 884 if (mMinimumLogicalFontSize != size) { 885 mMinimumLogicalFontSize = size; 886 postSync(); 887 } 888 } 889 890 /** 891 * Get the minimum logical font size. The default is 8. 892 * @return A non-negative integer between 1 and 72. 893 */ 894 public synchronized int getMinimumLogicalFontSize() { 895 return mMinimumLogicalFontSize; 896 } 897 898 /** 899 * Set the default font size. 900 * @param size A non-negative integer between 1 and 72. 901 * Any number outside the specified range will be pinned. 902 */ 903 public synchronized void setDefaultFontSize(int size) { 904 size = pin(size); 905 if (mDefaultFontSize != size) { 906 mDefaultFontSize = size; 907 postSync(); 908 } 909 } 910 911 /** 912 * Get the default font size. The default is 16. 913 * @return A non-negative integer between 1 and 72. 914 */ 915 public synchronized int getDefaultFontSize() { 916 return mDefaultFontSize; 917 } 918 919 /** 920 * Set the default fixed font size. 921 * @param size A non-negative integer between 1 and 72. 922 * Any number outside the specified range will be pinned. 923 */ 924 public synchronized void setDefaultFixedFontSize(int size) { 925 size = pin(size); 926 if (mDefaultFixedFontSize != size) { 927 mDefaultFixedFontSize = size; 928 postSync(); 929 } 930 } 931 932 /** 933 * Get the default fixed font size. The default is 16. 934 * @return A non-negative integer between 1 and 72. 935 */ 936 public synchronized int getDefaultFixedFontSize() { 937 return mDefaultFixedFontSize; 938 } 939 940 /** 941 * Set the number of pages cached by the WebKit for the history navigation. 942 * @param size A non-negative integer between 0 (no cache) and 20 (max). 943 * @hide 944 */ 945 public synchronized void setPageCacheCapacity(int size) { 946 if (size < 0) size = 0; 947 if (size > 20) size = 20; 948 if (mPageCacheCapacity != size) { 949 mPageCacheCapacity = size; 950 postSync(); 951 } 952 } 953 954 /** 955 * Tell the WebView to load image resources automatically. 956 * @param flag True if the WebView should load images automatically. 957 */ 958 public synchronized void setLoadsImagesAutomatically(boolean flag) { 959 if (mLoadsImagesAutomatically != flag) { 960 mLoadsImagesAutomatically = flag; 961 postSync(); 962 } 963 } 964 965 /** 966 * Return true if the WebView will load image resources automatically. 967 * The default is true. 968 * @return True if the WebView loads images automatically. 969 */ 970 public synchronized boolean getLoadsImagesAutomatically() { 971 return mLoadsImagesAutomatically; 972 } 973 974 /** 975 * Tell the WebView to block network images. This is only checked when 976 * {@link #getLoadsImagesAutomatically} is true. If you set the value to 977 * false, images will automatically be loaded. Use this api to reduce 978 * bandwidth only. Use {@link #setBlockNetworkLoads} if possible. 979 * @param flag True if the WebView should block network images. 980 * @see #setBlockNetworkLoads 981 */ 982 public synchronized void setBlockNetworkImage(boolean flag) { 983 if (mBlockNetworkImage != flag) { 984 mBlockNetworkImage = flag; 985 postSync(); 986 } 987 } 988 989 /** 990 * Return true if the WebView will block network images. The default is 991 * false. 992 * @return True if the WebView blocks network images. 993 */ 994 public synchronized boolean getBlockNetworkImage() { 995 return mBlockNetworkImage; 996 } 997 998 /** 999 * Tell the WebView to block all network load requests. If you set the 1000 * value to false, you must call {@link android.webkit.WebView#reload} to 1001 * fetch remote resources. This flag supercedes the value passed to 1002 * {@link #setBlockNetworkImage}. 1003 * @param flag True if the WebView should block all network loads. 1004 * @see android.webkit.WebView#reload 1005 */ 1006 public synchronized void setBlockNetworkLoads(boolean flag) { 1007 if (mBlockNetworkLoads != flag) { 1008 mBlockNetworkLoads = flag; 1009 verifyNetworkAccess(); 1010 } 1011 } 1012 1013 /** 1014 * Return true if the WebView will block all network loads. The default is 1015 * false. 1016 * @return True if the WebView blocks all network loads. 1017 */ 1018 public synchronized boolean getBlockNetworkLoads() { 1019 return mBlockNetworkLoads; 1020 } 1021 1022 1023 private void verifyNetworkAccess() { 1024 if (!mBlockNetworkLoads) { 1025 if (mContext.checkPermission("android.permission.INTERNET", 1026 android.os.Process.myPid(), android.os.Process.myUid()) != 1027 PackageManager.PERMISSION_GRANTED) { 1028 throw new SecurityException 1029 ("Permission denied - " + 1030 "application missing INTERNET permission"); 1031 } 1032 } 1033 } 1034 1035 /** 1036 * Tell the WebView to enable javascript execution. 1037 * @param flag True if the WebView should execute javascript. 1038 */ 1039 public synchronized void setJavaScriptEnabled(boolean flag) { 1040 if (mJavaScriptEnabled != flag) { 1041 mJavaScriptEnabled = flag; 1042 postSync(); 1043 } 1044 } 1045 1046 /** 1047 * Tell the WebView to enable plugins. 1048 * @param flag True if the WebView should load plugins. 1049 * @deprecated This method has been deprecated in favor of 1050 * {@link #setPluginState} 1051 */ 1052 public synchronized void setPluginsEnabled(boolean flag) { 1053 setPluginState(PluginState.ON); 1054 } 1055 1056 /** 1057 * Tell the WebView to enable, disable, or have plugins on demand. On 1058 * demand mode means that if a plugin exists that can handle the embedded 1059 * content, a placeholder icon will be shown instead of the plugin. When 1060 * the placeholder is clicked, the plugin will be enabled. 1061 * @param state One of the PluginState values. 1062 */ 1063 public synchronized void setPluginState(PluginState state) { 1064 if (mPluginState != state) { 1065 mPluginState = state; 1066 postSync(); 1067 } 1068 } 1069 1070 /** 1071 * TODO: need to add @Deprecated 1072 */ 1073 public synchronized void setPluginsPath(String pluginsPath) { 1074 } 1075 1076 /** 1077 * Set the path to where database storage API databases should be saved. 1078 * Nota that the WebCore Database Tracker only allows the path to be set once. 1079 * This will update WebCore when the Sync runs in the C++ side. 1080 * @param databasePath String path to the directory where databases should 1081 * be saved. May be the empty string but should never be null. 1082 */ 1083 public synchronized void setDatabasePath(String databasePath) { 1084 if (databasePath != null && !mDatabasePathHasBeenSet) { 1085 mDatabasePath = databasePath; 1086 mDatabasePathHasBeenSet = true; 1087 postSync(); 1088 } 1089 } 1090 1091 /** 1092 * Set the path where the Geolocation permissions database should be saved. 1093 * This will update WebCore when the Sync runs in the C++ side. 1094 * @param databasePath String path to the directory where the Geolocation 1095 * permissions database should be saved. May be the empty string but 1096 * should never be null. 1097 */ 1098 public synchronized void setGeolocationDatabasePath(String databasePath) { 1099 if (databasePath != null 1100 && !databasePath.equals(mGeolocationDatabasePath)) { 1101 mGeolocationDatabasePath = databasePath; 1102 postSync(); 1103 } 1104 } 1105 1106 /** 1107 * Tell the WebView to enable Application Caches API. 1108 * @param flag True if the WebView should enable Application Caches. 1109 */ 1110 public synchronized void setAppCacheEnabled(boolean flag) { 1111 if (mAppCacheEnabled != flag) { 1112 mAppCacheEnabled = flag; 1113 postSync(); 1114 } 1115 } 1116 1117 /** 1118 * Set a custom path to the Application Caches files. The client 1119 * must ensure it exists before this call. 1120 * @param appCachePath String path to the directory containing Application 1121 * Caches files. The appCache path can be the empty string but should not 1122 * be null. Passing null for this parameter will result in a no-op. 1123 */ 1124 public synchronized void setAppCachePath(String appCachePath) { 1125 if (appCachePath != null && !appCachePath.equals(mAppCachePath)) { 1126 mAppCachePath = appCachePath; 1127 postSync(); 1128 } 1129 } 1130 1131 /** 1132 * Set the maximum size for the Application Caches content. 1133 * @param appCacheMaxSize the maximum size in bytes. 1134 */ 1135 public synchronized void setAppCacheMaxSize(long appCacheMaxSize) { 1136 if (appCacheMaxSize != mAppCacheMaxSize) { 1137 mAppCacheMaxSize = appCacheMaxSize; 1138 postSync(); 1139 } 1140 } 1141 1142 /** 1143 * Set whether the database storage API is enabled. 1144 * @param flag boolean True if the WebView should use the database storage 1145 * API. 1146 */ 1147 public synchronized void setDatabaseEnabled(boolean flag) { 1148 if (mDatabaseEnabled != flag) { 1149 mDatabaseEnabled = flag; 1150 postSync(); 1151 } 1152 } 1153 1154 /** 1155 * Set whether the DOM storage API is enabled. 1156 * @param flag boolean True if the WebView should use the DOM storage 1157 * API. 1158 */ 1159 public synchronized void setDomStorageEnabled(boolean flag) { 1160 if (mDomStorageEnabled != flag) { 1161 mDomStorageEnabled = flag; 1162 postSync(); 1163 } 1164 } 1165 1166 /** 1167 * Returns true if the DOM Storage API's are enabled. 1168 * @return True if the DOM Storage API's are enabled. 1169 */ 1170 public synchronized boolean getDomStorageEnabled() { 1171 return mDomStorageEnabled; 1172 } 1173 1174 /** 1175 * Return the path to where database storage API databases are saved for 1176 * the current WebView. 1177 * @return the String path to the database storage API databases. 1178 */ 1179 public synchronized String getDatabasePath() { 1180 return mDatabasePath; 1181 } 1182 1183 /** 1184 * Returns true if database storage API is enabled. 1185 * @return True if the database storage API is enabled. 1186 */ 1187 public synchronized boolean getDatabaseEnabled() { 1188 return mDatabaseEnabled; 1189 } 1190 1191 /** 1192 * Tell the WebView to enable WebWorkers API. 1193 * @param flag True if the WebView should enable WebWorkers. 1194 * Note that this flag only affects V8. JSC does not have 1195 * an equivalent setting. 1196 * @hide pending api council approval 1197 */ 1198 public synchronized void setWorkersEnabled(boolean flag) { 1199 if (mWorkersEnabled != flag) { 1200 mWorkersEnabled = flag; 1201 postSync(); 1202 } 1203 } 1204 1205 /** 1206 * Sets whether Geolocation is enabled. 1207 * @param flag Whether Geolocation should be enabled. 1208 */ 1209 public synchronized void setGeolocationEnabled(boolean flag) { 1210 if (mGeolocationEnabled != flag) { 1211 mGeolocationEnabled = flag; 1212 postSync(); 1213 } 1214 } 1215 1216 /** 1217 * Return true if javascript is enabled. <b>Note: The default is false.</b> 1218 * @return True if javascript is enabled. 1219 */ 1220 public synchronized boolean getJavaScriptEnabled() { 1221 return mJavaScriptEnabled; 1222 } 1223 1224 /** 1225 * Return true if plugins are enabled. 1226 * @return True if plugins are enabled. 1227 * @deprecated This method has been replaced by {@link #getPluginState} 1228 */ 1229 public synchronized boolean getPluginsEnabled() { 1230 return mPluginState == PluginState.ON; 1231 } 1232 1233 /** 1234 * Return the current plugin state. 1235 * @return A value corresponding to the enum PluginState. 1236 */ 1237 public synchronized PluginState getPluginState() { 1238 return mPluginState; 1239 } 1240 1241 /** 1242 * TODO: need to add @Deprecated 1243 */ 1244 public synchronized String getPluginsPath() { 1245 return ""; 1246 } 1247 1248 /** 1249 * Tell javascript to open windows automatically. This applies to the 1250 * javascript function window.open(). 1251 * @param flag True if javascript can open windows automatically. 1252 */ 1253 public synchronized void setJavaScriptCanOpenWindowsAutomatically( 1254 boolean flag) { 1255 if (mJavaScriptCanOpenWindowsAutomatically != flag) { 1256 mJavaScriptCanOpenWindowsAutomatically = flag; 1257 postSync(); 1258 } 1259 } 1260 1261 /** 1262 * Return true if javascript can open windows automatically. The default 1263 * is false. 1264 * @return True if javascript can open windows automatically during 1265 * window.open(). 1266 */ 1267 public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() { 1268 return mJavaScriptCanOpenWindowsAutomatically; 1269 } 1270 1271 /** 1272 * Set the default text encoding name to use when decoding html pages. 1273 * @param encoding The text encoding name. 1274 */ 1275 public synchronized void setDefaultTextEncodingName(String encoding) { 1276 if (encoding != null && !encoding.equals(mDefaultTextEncoding)) { 1277 mDefaultTextEncoding = encoding; 1278 postSync(); 1279 } 1280 } 1281 1282 /** 1283 * Get the default text encoding name. The default is "Latin-1". 1284 * @return The default text encoding name as a string. 1285 */ 1286 public synchronized String getDefaultTextEncodingName() { 1287 return mDefaultTextEncoding; 1288 } 1289 1290 /** 1291 * Set the WebView's user-agent string. If the string "ua" is null or empty, 1292 * it will use the system default user-agent string. 1293 */ 1294 public synchronized void setUserAgentString(String ua) { 1295 if (ua == null || ua.length() == 0) { 1296 synchronized(sLockForLocaleSettings) { 1297 Locale currentLocale = Locale.getDefault(); 1298 if (!sLocale.equals(currentLocale)) { 1299 sLocale = currentLocale; 1300 mAcceptLanguage = getCurrentAcceptLanguage(); 1301 } 1302 } 1303 ua = getCurrentUserAgent(); 1304 mUseDefaultUserAgent = true; 1305 } else { 1306 mUseDefaultUserAgent = false; 1307 } 1308 1309 if (!ua.equals(mUserAgent)) { 1310 mUserAgent = ua; 1311 postSync(); 1312 } 1313 } 1314 1315 /** 1316 * Return the WebView's user-agent string. 1317 */ 1318 public synchronized String getUserAgentString() { 1319 if (DESKTOP_USERAGENT.equals(mUserAgent) || 1320 IPHONE_USERAGENT.equals(mUserAgent) || 1321 !mUseDefaultUserAgent) { 1322 return mUserAgent; 1323 } 1324 1325 boolean doPostSync = false; 1326 synchronized(sLockForLocaleSettings) { 1327 Locale currentLocale = Locale.getDefault(); 1328 if (!sLocale.equals(currentLocale)) { 1329 sLocale = currentLocale; 1330 mUserAgent = getCurrentUserAgent(); 1331 mAcceptLanguage = getCurrentAcceptLanguage(); 1332 doPostSync = true; 1333 } 1334 } 1335 if (doPostSync) { 1336 postSync(); 1337 } 1338 return mUserAgent; 1339 } 1340 1341 /* package api to grab the Accept Language string. */ 1342 /*package*/ synchronized String getAcceptLanguage() { 1343 synchronized(sLockForLocaleSettings) { 1344 Locale currentLocale = Locale.getDefault(); 1345 if (!sLocale.equals(currentLocale)) { 1346 sLocale = currentLocale; 1347 mAcceptLanguage = getCurrentAcceptLanguage(); 1348 } 1349 } 1350 return mAcceptLanguage; 1351 } 1352 1353 /** 1354 * Tell the WebView whether it needs to set a node to have focus when 1355 * {@link WebView#requestFocus(int, android.graphics.Rect)} is called. 1356 * 1357 * @param flag 1358 */ 1359 public void setNeedInitialFocus(boolean flag) { 1360 if (mNeedInitialFocus != flag) { 1361 mNeedInitialFocus = flag; 1362 } 1363 } 1364 1365 /* Package api to get the choice whether it needs to set initial focus. */ 1366 /* package */ boolean getNeedInitialFocus() { 1367 return mNeedInitialFocus; 1368 } 1369 1370 /** 1371 * Set the priority of the Render thread. Unlike the other settings, this 1372 * one only needs to be called once per process. The default is NORMAL. 1373 * 1374 * @param priority RenderPriority, can be normal, high or low. 1375 */ 1376 public synchronized void setRenderPriority(RenderPriority priority) { 1377 if (mRenderPriority != priority) { 1378 mRenderPriority = priority; 1379 mEventHandler.sendMessage(Message.obtain(null, 1380 EventHandler.PRIORITY)); 1381 } 1382 } 1383 1384 /** 1385 * Override the way the cache is used. The way the cache is used is based 1386 * on the navigation option. For a normal page load, the cache is checked 1387 * and content is re-validated as needed. When navigating back, content is 1388 * not revalidated, instead the content is just pulled from the cache. 1389 * This function allows the client to override this behavior. 1390 * @param mode One of the LOAD_ values. 1391 */ 1392 public void setCacheMode(int mode) { 1393 if (mode != mOverrideCacheMode) { 1394 mOverrideCacheMode = mode; 1395 } 1396 } 1397 1398 /** 1399 * Return the current setting for overriding the cache mode. For a full 1400 * description, see the {@link #setCacheMode(int)} function. 1401 */ 1402 public int getCacheMode() { 1403 return mOverrideCacheMode; 1404 } 1405 1406 /** 1407 * If set, webkit alternately shrinks and expands images viewed outside 1408 * of an HTML page to fit the screen. This conflicts with attempts by 1409 * the UI to zoom in and out of an image, so it is set false by default. 1410 * @param shrink Set true to let webkit shrink the standalone image to fit. 1411 * {@hide} 1412 */ 1413 public void setShrinksStandaloneImagesToFit(boolean shrink) { 1414 if (mShrinksStandaloneImagesToFit != shrink) { 1415 mShrinksStandaloneImagesToFit = shrink; 1416 postSync(); 1417 } 1418 } 1419 1420 int getDoubleTapToastCount() { 1421 return mDoubleTapToastCount; 1422 } 1423 1424 void setDoubleTapToastCount(int count) { 1425 if (mDoubleTapToastCount != count) { 1426 mDoubleTapToastCount = count; 1427 // write the settings in the non-UI thread 1428 mEventHandler.sendMessage(Message.obtain(null, 1429 EventHandler.SET_DOUBLE_TAP_TOAST_COUNT)); 1430 } 1431 } 1432 1433 /** 1434 * Transfer messages from the queue to the new WebCoreThread. Called from 1435 * WebCore thread. 1436 */ 1437 /*package*/ 1438 synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) { 1439 mBrowserFrame = frame; 1440 if (DebugFlags.WEB_SETTINGS) { 1441 junit.framework.Assert.assertTrue(frame.mNativeFrame != 0); 1442 } 1443 1444 SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE, 1445 Context.MODE_PRIVATE); 1446 if (mDoubleTapToastCount > 0) { 1447 mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT, 1448 mDoubleTapToastCount); 1449 } 1450 nativeSync(frame.mNativeFrame); 1451 mSyncPending = false; 1452 mEventHandler.createHandler(); 1453 } 1454 1455 /** 1456 * Let the Settings object know that our owner is being destroyed. 1457 */ 1458 /*package*/ 1459 synchronized void onDestroyed() { 1460 } 1461 1462 private int pin(int size) { 1463 // FIXME: 72 is just an arbitrary max text size value. 1464 if (size < 1) { 1465 return 1; 1466 } else if (size > 72) { 1467 return 72; 1468 } 1469 return size; 1470 } 1471 1472 /* Post a SYNC message to handle syncing the native settings. */ 1473 private synchronized void postSync() { 1474 // Only post if a sync is not pending 1475 if (!mSyncPending) { 1476 mSyncPending = mEventHandler.sendMessage( 1477 Message.obtain(null, EventHandler.SYNC)); 1478 } 1479 } 1480 1481 // Synchronize the native and java settings. 1482 private native void nativeSync(int nativeFrame); 1483} 1484