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