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