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