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