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