Home | History | Annotate | Download | only in webkit
      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.DisplayMetrics;
     26 import android.util.EventLog;
     27 
     28 import java.util.Locale;
     29 
     30 /**
     31  * Manages settings state for a WebView. When a WebView is first created, it
     32  * obtains a set of default settings. These default settings will be returned
     33  * from any getter call. A WebSettings object obtained from
     34  * WebView.getSettings() is tied to the life of the WebView. If a WebView has
     35  * been destroyed, any method call on WebSettings will throw an
     36  * IllegalStateException.
     37  */
     38 public class WebSettings {
     39     /**
     40      * Enum for controlling the layout of html.
     41      * NORMAL means no rendering changes.
     42      * SINGLE_COLUMN moves all content into one column that is the width of the
     43      * view.
     44      * NARROW_COLUMNS makes all columns no wider than the screen if possible.
     45      */
     46     // XXX: These must match LayoutAlgorithm in Settings.h in WebCore.
     47     public enum LayoutAlgorithm {
     48         NORMAL,
     49         /**
     50          * @deprecated This algorithm is now obsolete.
     51          */
     52         @Deprecated
     53         SINGLE_COLUMN,
     54         NARROW_COLUMNS
     55     }
     56 
     57     /**
     58      * Enum for specifying the text size.
     59      * SMALLEST is 50%
     60      * SMALLER is 75%
     61      * NORMAL is 100%
     62      * LARGER is 150%
     63      * LARGEST is 200%
     64      * @deprecated Use {@link WebSettings#setTextZoom(int)} and {@link WebSettings#getTextZoom()} instead.
     65      */
     66     public enum TextSize {
     67         SMALLEST(50),
     68         SMALLER(75),
     69         NORMAL(100),
     70         LARGER(150),
     71         LARGEST(200);
     72         TextSize(int size) {
     73             value = size;
     74         }
     75         int value;
     76     }
     77 
     78     /**
     79      * Enum for specifying the WebView's desired density.
     80      * FAR makes 100% looking like in 240dpi
     81      * MEDIUM makes 100% looking like in 160dpi
     82      * CLOSE makes 100% looking like in 120dpi
     83      */
     84     public enum ZoomDensity {
     85         FAR(150),      // 240dpi
     86         MEDIUM(100),    // 160dpi
     87         CLOSE(75);     // 120dpi
     88         ZoomDensity(int size) {
     89             value = size;
     90         }
     91         int value;
     92     }
     93 
     94     /**
     95      * Default cache usage pattern  Use with {@link #setCacheMode}.
     96      */
     97     public static final int LOAD_DEFAULT = -1;
     98 
     99     /**
    100      * Normal cache usage pattern  Use with {@link #setCacheMode}.
    101      */
    102     public static final int LOAD_NORMAL = 0;
    103 
    104     /**
    105      * Use cache if content is there, even if expired (eg, history nav)
    106      * If it is not in the cache, load from network.
    107      * Use with {@link #setCacheMode}.
    108      */
    109     public static final int LOAD_CACHE_ELSE_NETWORK = 1;
    110 
    111     /**
    112      * Don't use the cache, load from network
    113      * Use with {@link #setCacheMode}.
    114      */
    115     public static final int LOAD_NO_CACHE = 2;
    116 
    117     /**
    118      * Don't use the network, load from cache only.
    119      * Use with {@link #setCacheMode}.
    120      */
    121     public static final int LOAD_CACHE_ONLY = 3;
    122 
    123     public enum RenderPriority {
    124         NORMAL,
    125         HIGH,
    126         LOW
    127     }
    128 
    129     /**
    130      * The plugin state effects how plugins are treated on a page. ON means
    131      * that any object will be loaded even if a plugin does not exist to handle
    132      * the content. ON_DEMAND means that if there is a plugin installed that
    133      * can handle the content, a placeholder is shown until the user clicks on
    134      * the placeholder. Once clicked, the plugin will be enabled on the page.
    135      * OFF means that all plugins will be turned off and any fallback content
    136      * will be used.
    137      */
    138     public enum PluginState {
    139         ON,
    140         ON_DEMAND,
    141         OFF
    142     }
    143 
    144     // TODO: Keep this up to date
    145     private static final String PREVIOUS_VERSION = "3.1";
    146 
    147     // WebView associated with this WebSettings.
    148     private WebView mWebView;
    149     // BrowserFrame used to access the native frame pointer.
    150     private BrowserFrame mBrowserFrame;
    151     // Flag to prevent multiple SYNC messages at one time.
    152     private boolean mSyncPending = false;
    153     // Custom handler that queues messages until the WebCore thread is active.
    154     private final EventHandler mEventHandler;
    155 
    156     // Private settings so we don't have to go into native code to
    157     // retrieve the values. After setXXX, postSync() needs to be called.
    158     //
    159     // The default values need to match those in WebSettings.cpp
    160     // If the defaults change, please also update the JavaDocs so developers
    161     // know what they are.
    162     private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
    163     private Context         mContext;
    164     private int             mTextSize = 100;
    165     private String          mStandardFontFamily = "sans-serif";
    166     private String          mFixedFontFamily = "monospace";
    167     private String          mSansSerifFontFamily = "sans-serif";
    168     private String          mSerifFontFamily = "serif";
    169     private String          mCursiveFontFamily = "cursive";
    170     private String          mFantasyFontFamily = "fantasy";
    171     private String          mDefaultTextEncoding;
    172     private String          mUserAgent;
    173     private boolean         mUseDefaultUserAgent;
    174     private String          mAcceptLanguage;
    175     private int             mMinimumFontSize = 8;
    176     private int             mMinimumLogicalFontSize = 8;
    177     private int             mDefaultFontSize = 16;
    178     private int             mDefaultFixedFontSize = 13;
    179     private int             mPageCacheCapacity = 0;
    180     private boolean         mLoadsImagesAutomatically = true;
    181     private boolean         mBlockNetworkImage = false;
    182     private boolean         mBlockNetworkLoads;
    183     private boolean         mJavaScriptEnabled = false;
    184     private boolean         mHardwareAccelSkia = false;
    185     private boolean         mShowVisualIndicator = false;
    186     private PluginState     mPluginState = PluginState.OFF;
    187     private boolean         mJavaScriptCanOpenWindowsAutomatically = false;
    188     private boolean         mUseDoubleTree = false;
    189     private boolean         mUseWideViewport = false;
    190     private boolean         mSupportMultipleWindows = false;
    191     private boolean         mShrinksStandaloneImagesToFit = false;
    192     private long            mMaximumDecodedImageSize = 0; // 0 means default
    193     private boolean         mPrivateBrowsingEnabled = false;
    194     private boolean         mSyntheticLinksEnabled = true;
    195     // HTML5 API flags
    196     private boolean         mAppCacheEnabled = false;
    197     private boolean         mDatabaseEnabled = false;
    198     private boolean         mDomStorageEnabled = false;
    199     private boolean         mWorkersEnabled = false;  // only affects V8.
    200     private boolean         mGeolocationEnabled = true;
    201     private boolean         mXSSAuditorEnabled = false;
    202     // HTML5 configuration parameters
    203     private long            mAppCacheMaxSize = Long.MAX_VALUE;
    204     private String          mAppCachePath = "";
    205     private String          mDatabasePath = "";
    206     // The WebCore DatabaseTracker only allows the database path to be set
    207     // once. Keep track of when the path has been set.
    208     private boolean         mDatabasePathHasBeenSet = false;
    209     private String          mGeolocationDatabasePath = "";
    210     // Don't need to synchronize the get/set methods as they
    211     // are basic types, also none of these values are used in
    212     // native WebCore code.
    213     private ZoomDensity     mDefaultZoom = ZoomDensity.MEDIUM;
    214     private RenderPriority  mRenderPriority = RenderPriority.NORMAL;
    215     private int             mOverrideCacheMode = LOAD_DEFAULT;
    216     private int             mDoubleTapZoom = 100;
    217     private boolean         mSaveFormData = true;
    218     private boolean         mAutoFillEnabled = false;
    219     private boolean         mSavePassword = true;
    220     private boolean         mLightTouchEnabled = false;
    221     private boolean         mNeedInitialFocus = true;
    222     private boolean         mNavDump = false;
    223     private boolean         mSupportZoom = true;
    224     private boolean         mBuiltInZoomControls = false;
    225     private boolean         mDisplayZoomControls = true;
    226     private boolean         mAllowFileAccess = true;
    227     private boolean         mAllowContentAccess = true;
    228     private boolean         mLoadWithOverviewMode = false;
    229     private boolean         mEnableSmoothTransition = false;
    230     private boolean         mForceUserScalable = false;
    231 
    232     // AutoFill Profile data
    233     /**
    234      * @hide for now, pending API council approval.
    235      */
    236     public static class AutoFillProfile {
    237         private int mUniqueId;
    238         private String mFullName;
    239         private String mEmailAddress;
    240         private String mCompanyName;
    241         private String mAddressLine1;
    242         private String mAddressLine2;
    243         private String mCity;
    244         private String mState;
    245         private String mZipCode;
    246         private String mCountry;
    247         private String mPhoneNumber;
    248 
    249         public AutoFillProfile(int uniqueId, String fullName, String email,
    250                 String companyName, String addressLine1, String addressLine2,
    251                 String city, String state, String zipCode, String country,
    252                 String phoneNumber) {
    253             mUniqueId = uniqueId;
    254             mFullName = fullName;
    255             mEmailAddress = email;
    256             mCompanyName = companyName;
    257             mAddressLine1 = addressLine1;
    258             mAddressLine2 = addressLine2;
    259             mCity = city;
    260             mState = state;
    261             mZipCode = zipCode;
    262             mCountry = country;
    263             mPhoneNumber = phoneNumber;
    264         }
    265 
    266         public int getUniqueId() { return mUniqueId; }
    267         public String getFullName() { return mFullName; }
    268         public String getEmailAddress() { return mEmailAddress; }
    269         public String getCompanyName() { return mCompanyName; }
    270         public String getAddressLine1() { return mAddressLine1; }
    271         public String getAddressLine2() { return mAddressLine2; }
    272         public String getCity() { return mCity; }
    273         public String getState() { return mState; }
    274         public String getZipCode() { return mZipCode; }
    275         public String getCountry() { return mCountry; }
    276         public String getPhoneNumber() { return mPhoneNumber; }
    277     }
    278 
    279 
    280     private AutoFillProfile mAutoFillProfile;
    281 
    282     private boolean         mUseWebViewBackgroundForOverscroll = true;
    283 
    284     // private WebSettings, not accessible by the host activity
    285     static private int      mDoubleTapToastCount = 3;
    286 
    287     private static final String PREF_FILE = "WebViewSettings";
    288     private static final String DOUBLE_TAP_TOAST_COUNT = "double_tap_toast_count";
    289 
    290     // Class to handle messages before WebCore is ready.
    291     private class EventHandler {
    292         // Message id for syncing
    293         static final int SYNC = 0;
    294         // Message id for setting priority
    295         static final int PRIORITY = 1;
    296         // Message id for writing double-tap toast count
    297         static final int SET_DOUBLE_TAP_TOAST_COUNT = 2;
    298         // Actual WebCore thread handler
    299         private Handler mHandler;
    300 
    301         private synchronized void createHandler() {
    302             // as mRenderPriority can be set before thread is running, sync up
    303             setRenderPriority();
    304 
    305             // create a new handler
    306             mHandler = new Handler() {
    307                 @Override
    308                 public void handleMessage(Message msg) {
    309                     switch (msg.what) {
    310                         case SYNC:
    311                             synchronized (WebSettings.this) {
    312                                 if (mBrowserFrame.mNativeFrame != 0) {
    313                                     nativeSync(mBrowserFrame.mNativeFrame);
    314                                 }
    315                                 mSyncPending = false;
    316                             }
    317                             break;
    318 
    319                         case PRIORITY: {
    320                             setRenderPriority();
    321                             break;
    322                         }
    323 
    324                         case SET_DOUBLE_TAP_TOAST_COUNT: {
    325                             SharedPreferences.Editor editor = mContext
    326                                     .getSharedPreferences(PREF_FILE,
    327                                             Context.MODE_PRIVATE).edit();
    328                             editor.putInt(DOUBLE_TAP_TOAST_COUNT,
    329                                     mDoubleTapToastCount);
    330                             editor.commit();
    331                             break;
    332                         }
    333                     }
    334                 }
    335             };
    336         }
    337 
    338         private void setRenderPriority() {
    339             synchronized (WebSettings.this) {
    340                 if (mRenderPriority == RenderPriority.NORMAL) {
    341                     android.os.Process.setThreadPriority(
    342                             android.os.Process.THREAD_PRIORITY_DEFAULT);
    343                 } else if (mRenderPriority == RenderPriority.HIGH) {
    344                     android.os.Process.setThreadPriority(
    345                             android.os.Process.THREAD_PRIORITY_FOREGROUND +
    346                             android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
    347                 } else if (mRenderPriority == RenderPriority.LOW) {
    348                     android.os.Process.setThreadPriority(
    349                             android.os.Process.THREAD_PRIORITY_BACKGROUND);
    350                 }
    351             }
    352         }
    353 
    354         /**
    355          * Send a message to the private queue or handler.
    356          */
    357         private synchronized boolean sendMessage(Message msg) {
    358             if (mHandler != null) {
    359                 mHandler.sendMessage(msg);
    360                 return true;
    361             } else {
    362                 return false;
    363             }
    364         }
    365     }
    366 
    367     // User agent strings.
    368     private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (X11; " +
    369         "Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) " +
    370         "Chrome/11.0.696.34 Safari/534.24";
    371     private static final String IPHONE_USERAGENT =
    372             "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)"
    373             + " AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0"
    374             + " Mobile/7A341 Safari/528.16";
    375     private static Locale sLocale;
    376     private static Object sLockForLocaleSettings;
    377 
    378     /**
    379      * Package constructor to prevent clients from creating a new settings
    380      * instance.
    381      */
    382     WebSettings(Context context, WebView webview) {
    383         mEventHandler = new EventHandler();
    384         mContext = context;
    385         mWebView = webview;
    386         mDefaultTextEncoding = context.getString(com.android.internal.
    387                                                  R.string.default_text_encoding);
    388 
    389         if (sLockForLocaleSettings == null) {
    390             sLockForLocaleSettings = new Object();
    391             sLocale = Locale.getDefault();
    392         }
    393         mAcceptLanguage = getCurrentAcceptLanguage();
    394         mUserAgent = getCurrentUserAgent();
    395         mUseDefaultUserAgent = true;
    396 
    397         mBlockNetworkLoads = mContext.checkPermission(
    398                 "android.permission.INTERNET", android.os.Process.myPid(),
    399                 android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED;
    400     }
    401 
    402     private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";
    403 
    404     /**
    405      * Looks at sLocale and returns current AcceptLanguage String.
    406      * @return Current AcceptLanguage String.
    407      */
    408     private String getCurrentAcceptLanguage() {
    409         Locale locale;
    410         synchronized(sLockForLocaleSettings) {
    411             locale = sLocale;
    412         }
    413         StringBuilder buffer = new StringBuilder();
    414         addLocaleToHttpAcceptLanguage(buffer, locale);
    415 
    416         if (!Locale.US.equals(locale)) {
    417             if (buffer.length() > 0) {
    418                 buffer.append(", ");
    419             }
    420             buffer.append(ACCEPT_LANG_FOR_US_LOCALE);
    421         }
    422 
    423         return buffer.toString();
    424     }
    425 
    426     /**
    427      * Convert obsolete language codes, including Hebrew/Indonesian/Yiddish,
    428      * to new standard.
    429      */
    430     private static String convertObsoleteLanguageCodeToNew(String langCode) {
    431         if (langCode == null) {
    432             return null;
    433         }
    434         if ("iw".equals(langCode)) {
    435             // Hebrew
    436             return "he";
    437         } else if ("in".equals(langCode)) {
    438             // Indonesian
    439             return "id";
    440         } else if ("ji".equals(langCode)) {
    441             // Yiddish
    442             return "yi";
    443         }
    444         return langCode;
    445     }
    446 
    447     private static void addLocaleToHttpAcceptLanguage(StringBuilder builder,
    448                                                       Locale locale) {
    449         String language = convertObsoleteLanguageCodeToNew(locale.getLanguage());
    450         if (language != null) {
    451             builder.append(language);
    452             String country = locale.getCountry();
    453             if (country != null) {
    454                 builder.append("-");
    455                 builder.append(country);
    456             }
    457         }
    458     }
    459 
    460     /**
    461      * Looks at sLocale and mContext and returns current UserAgent String.
    462      * @return Current UserAgent String.
    463      */
    464     private synchronized String getCurrentUserAgent() {
    465         Locale locale;
    466         synchronized(sLockForLocaleSettings) {
    467             locale = sLocale;
    468         }
    469         StringBuffer buffer = new StringBuffer();
    470         // Add version
    471         final String version = Build.VERSION.RELEASE;
    472         if (version.length() > 0) {
    473             if (Character.isDigit(version.charAt(0))) {
    474                 // Release is a version, eg "3.1"
    475                 buffer.append(version);
    476             } else {
    477                 // Release is a codename, eg "Honeycomb"
    478                 // In this case, use the previous release's version
    479                 buffer.append(PREVIOUS_VERSION);
    480             }
    481         } else {
    482             // default to "1.0"
    483             buffer.append("1.0");
    484         }
    485         buffer.append("; ");
    486         final String language = locale.getLanguage();
    487         if (language != null) {
    488             buffer.append(convertObsoleteLanguageCodeToNew(language));
    489             final String country = locale.getCountry();
    490             if (country != null) {
    491                 buffer.append("-");
    492                 buffer.append(country.toLowerCase());
    493             }
    494         } else {
    495             // default to "en"
    496             buffer.append("en");
    497         }
    498         buffer.append(";");
    499         // add the model for the release build
    500         if ("REL".equals(Build.VERSION.CODENAME)) {
    501             final String model = Build.MODEL;
    502             if (model.length() > 0) {
    503                 buffer.append(" ");
    504                 buffer.append(model);
    505             }
    506         }
    507         final String id = Build.ID;
    508         if (id.length() > 0) {
    509             buffer.append(" Build/");
    510             buffer.append(id);
    511         }
    512         String mobile = mContext.getResources().getText(
    513             com.android.internal.R.string.web_user_agent_target_content).toString();
    514         final String base = mContext.getResources().getText(
    515                 com.android.internal.R.string.web_user_agent).toString();
    516         return String.format(base, buffer, mobile);
    517     }
    518 
    519     /**
    520      * Enables dumping the pages navigation cache to a text file.
    521      * @deprecated This method is now obsolete.
    522      */
    523     @Deprecated
    524     public void setNavDump(boolean enabled) {
    525         mNavDump = enabled;
    526     }
    527 
    528     /**
    529      * Returns true if dumping the navigation cache is enabled.
    530      * @deprecated This method is now obsolete.
    531      */
    532     @Deprecated
    533     public boolean getNavDump() {
    534         return mNavDump;
    535     }
    536 
    537     /**
    538      * If WebView only supports touch, a different navigation model will be
    539      * applied. Otherwise, the navigation to support both touch and keyboard
    540      * will be used.
    541      * @hide
    542     public void setSupportTouchOnly(boolean touchOnly) {
    543         mSupportTounchOnly = touchOnly;
    544     }
    545      */
    546 
    547     boolean supportTouchOnly() {
    548         // for debug only, use mLightTouchEnabled for mSupportTounchOnly
    549         return mLightTouchEnabled;
    550     }
    551 
    552     /**
    553      * Set whether the WebView supports zoom
    554      */
    555     public void setSupportZoom(boolean support) {
    556         mSupportZoom = support;
    557         mWebView.updateMultiTouchSupport(mContext);
    558     }
    559 
    560     /**
    561      * Returns whether the WebView supports zoom
    562      */
    563     public boolean supportZoom() {
    564         return mSupportZoom;
    565     }
    566 
    567     /**
    568      * Sets whether the zoom mechanism built into WebView is used.
    569      */
    570     public void setBuiltInZoomControls(boolean enabled) {
    571         mBuiltInZoomControls = enabled;
    572         mWebView.updateMultiTouchSupport(mContext);
    573     }
    574 
    575     /**
    576      * Returns true if the zoom mechanism built into WebView is being used.
    577      */
    578     public boolean getBuiltInZoomControls() {
    579         return mBuiltInZoomControls;
    580     }
    581 
    582     /**
    583      * Sets whether the on screen zoom buttons are used.
    584      * A combination of built in zoom controls enabled
    585      * and on screen zoom controls disabled allows for pinch to zoom
    586      * to work without the on screen controls
    587      */
    588     public void setDisplayZoomControls(boolean enabled) {
    589         mDisplayZoomControls = enabled;
    590         mWebView.updateMultiTouchSupport(mContext);
    591     }
    592 
    593     /**
    594      * Returns true if the on screen zoom buttons are being used.
    595      */
    596     public boolean getDisplayZoomControls() {
    597         return mDisplayZoomControls;
    598     }
    599 
    600     /**
    601      * Enable or disable file access within WebView. File access is enabled by
    602      * default.  Note that this enables or disables file system access only.
    603      * Assets and resources are still accessible using file:///android_asset and
    604      * file:///android_res.
    605      */
    606     public void setAllowFileAccess(boolean allow) {
    607         mAllowFileAccess = allow;
    608     }
    609 
    610     /**
    611      * Returns true if this WebView supports file access.
    612      */
    613     public boolean getAllowFileAccess() {
    614         return mAllowFileAccess;
    615     }
    616 
    617     /**
    618      * Enable or disable content url access within WebView.  Content url access
    619      * allows WebView to load content from a content provider installed in the
    620      * system.  The default is enabled.
    621      */
    622     public void setAllowContentAccess(boolean allow) {
    623         mAllowContentAccess = allow;
    624     }
    625 
    626     /**
    627      * Returns true if this WebView supports content url access.
    628      */
    629     public boolean getAllowContentAccess() {
    630         return mAllowContentAccess;
    631     }
    632 
    633     /**
    634      * Set whether the WebView loads a page with overview mode.
    635      */
    636     public void setLoadWithOverviewMode(boolean overview) {
    637         mLoadWithOverviewMode = overview;
    638     }
    639 
    640     /**
    641      * Returns true if this WebView loads page with overview mode
    642      */
    643     public boolean getLoadWithOverviewMode() {
    644         return mLoadWithOverviewMode;
    645     }
    646 
    647     /**
    648      * Set whether the WebView will enable smooth transition while panning or
    649      * zooming or while the window hosting the WebView does not have focus.
    650      * If it is true, WebView will choose a solution to maximize the performance.
    651      * e.g. the WebView's content may not be updated during the transition.
    652      * If it is false, WebView will keep its fidelity. The default value is false.
    653      */
    654     public void setEnableSmoothTransition(boolean enable) {
    655         mEnableSmoothTransition = enable;
    656     }
    657 
    658     /**
    659      * Returns true if the WebView enables smooth transition while panning or
    660      * zooming.
    661      */
    662     public boolean enableSmoothTransition() {
    663         return mEnableSmoothTransition;
    664     }
    665 
    666     /**
    667      * Set whether the WebView uses its background for over scroll background.
    668      * If true, it will use the WebView's background. If false, it will use an
    669      * internal pattern. Default is true.
    670      * @deprecated This method is now obsolete.
    671      */
    672     @Deprecated
    673     public void setUseWebViewBackgroundForOverscrollBackground(boolean view) {
    674         mUseWebViewBackgroundForOverscroll = view;
    675     }
    676 
    677     /**
    678      * Returns true if this WebView uses WebView's background instead of
    679      * internal pattern for over scroll background.
    680      * @deprecated This method is now obsolete.
    681      */
    682     @Deprecated
    683     public boolean getUseWebViewBackgroundForOverscrollBackground() {
    684         return mUseWebViewBackgroundForOverscroll;
    685     }
    686 
    687     /**
    688      * Store whether the WebView is saving form data.
    689      */
    690     public void setSaveFormData(boolean save) {
    691         mSaveFormData = save;
    692     }
    693 
    694     /**
    695      *  Return whether the WebView is saving form data and displaying prior
    696      *  entries/autofill++.  Always false in private browsing mode.
    697      */
    698     public boolean getSaveFormData() {
    699         return mSaveFormData && !mPrivateBrowsingEnabled;
    700     }
    701 
    702     /**
    703      *  Store whether the WebView is saving password.
    704      */
    705     public void setSavePassword(boolean save) {
    706         mSavePassword = save;
    707     }
    708 
    709     /**
    710      *  Return whether the WebView is saving password.
    711      */
    712     public boolean getSavePassword() {
    713         return mSavePassword;
    714     }
    715 
    716     /**
    717      * Set the text zoom of the page in percent. Default is 100.
    718      * @param textZoom A percent value for increasing or decreasing the text.
    719      */
    720     public synchronized void setTextZoom(int textZoom) {
    721         if (mTextSize != textZoom) {
    722             if (WebView.mLogEvent) {
    723                 EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE,
    724                         mTextSize, textZoom);
    725             }
    726             mTextSize = textZoom;
    727             postSync();
    728         }
    729     }
    730 
    731     /**
    732      * Get the text zoom of the page in percent.
    733      * @return A percent value describing the text zoom.
    734      * @see setTextSizeZoom
    735      */
    736     public synchronized int getTextZoom() {
    737         return mTextSize;
    738     }
    739 
    740     /**
    741      * Set the text size of the page.
    742      * @param t A TextSize value for increasing or decreasing the text.
    743      * @see WebSettings.TextSize
    744      * @deprecated Use {@link #setTextZoom(int)} instead
    745      */
    746     public synchronized void setTextSize(TextSize t) {
    747         setTextZoom(t.value);
    748     }
    749 
    750     /**
    751      * Get the text size of the page. If the text size was previously specified
    752      * in percent using {@link #setTextZoom(int)}, this will return
    753      * the closest matching {@link TextSize}.
    754      * @return A TextSize enum value describing the text size.
    755      * @see WebSettings.TextSize
    756      * @deprecated Use {@link #getTextZoom()} instead
    757      */
    758     public synchronized TextSize getTextSize() {
    759         TextSize closestSize = null;
    760         int smallestDelta = Integer.MAX_VALUE;
    761         for (TextSize size : TextSize.values()) {
    762             int delta = Math.abs(mTextSize - size.value);
    763             if (delta == 0) {
    764                 return size;
    765             }
    766             if (delta < smallestDelta) {
    767                 smallestDelta = delta;
    768                 closestSize = size;
    769             }
    770         }
    771         return closestSize != null ? closestSize : TextSize.NORMAL;
    772     }
    773 
    774     /**
    775      * Set the double-tap zoom of the page in percent. Default is 100.
    776      * @param doubleTapZoom A percent value for increasing or decreasing the double-tap zoom.
    777      * @hide
    778      */
    779     public void setDoubleTapZoom(int doubleTapZoom) {
    780         if (mDoubleTapZoom != doubleTapZoom) {
    781             mDoubleTapZoom = doubleTapZoom;
    782             mWebView.updateDoubleTapZoom(doubleTapZoom);
    783         }
    784     }
    785 
    786     /**
    787      * Get the double-tap zoom of the page in percent.
    788      * @return A percent value describing the double-tap zoom.
    789      * @hide
    790      */
    791     public int getDoubleTapZoom() {
    792         return mDoubleTapZoom;
    793     }
    794 
    795     /**
    796      * Set the default zoom density of the page. This should be called from UI
    797      * thread.
    798      * @param zoom A ZoomDensity value
    799      * @see WebSettings.ZoomDensity
    800      */
    801     public void setDefaultZoom(ZoomDensity zoom) {
    802         if (mDefaultZoom != zoom) {
    803             mDefaultZoom = zoom;
    804             mWebView.adjustDefaultZoomDensity(zoom.value);
    805         }
    806     }
    807 
    808     /**
    809      * Get the default zoom density of the page. This should be called from UI
    810      * thread.
    811      * @return A ZoomDensity value
    812      * @see WebSettings.ZoomDensity
    813      */
    814     public ZoomDensity getDefaultZoom() {
    815         return mDefaultZoom;
    816     }
    817 
    818     /**
    819      * Enables using light touches to make a selection and activate mouseovers.
    820      */
    821     public void setLightTouchEnabled(boolean enabled) {
    822         mLightTouchEnabled = enabled;
    823     }
    824 
    825     /**
    826      * Returns true if light touches are enabled.
    827      */
    828     public boolean getLightTouchEnabled() {
    829         return mLightTouchEnabled;
    830     }
    831 
    832     /**
    833      * @deprecated This setting controlled a rendering optimization
    834      * that is no longer present. Setting it now has no effect.
    835      */
    836     @Deprecated
    837     public synchronized void setUseDoubleTree(boolean use) {
    838         return;
    839     }
    840 
    841     /**
    842      * @deprecated This setting controlled a rendering optimization
    843      * that is no longer present. Setting it now has no effect.
    844      */
    845     @Deprecated
    846     public synchronized boolean getUseDoubleTree() {
    847         return false;
    848     }
    849 
    850     /**
    851      * Tell the WebView about user-agent string.
    852      * @param ua 0 if the WebView should use an Android user-agent string,
    853      *           1 if the WebView should use a desktop user-agent string.
    854      *
    855      * @deprecated Please use setUserAgentString instead.
    856      */
    857     @Deprecated
    858     public synchronized void setUserAgent(int ua) {
    859         String uaString = null;
    860         if (ua == 1) {
    861             if (DESKTOP_USERAGENT.equals(mUserAgent)) {
    862                 return; // do nothing
    863             } else {
    864                 uaString = DESKTOP_USERAGENT;
    865             }
    866         } else if (ua == 2) {
    867             if (IPHONE_USERAGENT.equals(mUserAgent)) {
    868                 return; // do nothing
    869             } else {
    870                 uaString = IPHONE_USERAGENT;
    871             }
    872         } else if (ua != 0) {
    873             return; // do nothing
    874         }
    875         setUserAgentString(uaString);
    876     }
    877 
    878     /**
    879      * Return user-agent as int
    880      * @return int  0 if the WebView is using an Android user-agent string.
    881      *              1 if the WebView is using a desktop user-agent string.
    882      *             -1 if the WebView is using user defined user-agent string.
    883      *
    884      * @deprecated Please use getUserAgentString instead.
    885      */
    886     @Deprecated
    887     public synchronized int getUserAgent() {
    888         if (DESKTOP_USERAGENT.equals(mUserAgent)) {
    889             return 1;
    890         } else if (IPHONE_USERAGENT.equals(mUserAgent)) {
    891             return 2;
    892         } else if (mUseDefaultUserAgent) {
    893             return 0;
    894         }
    895         return -1;
    896     }
    897 
    898     /**
    899      * Tell the WebView to use the wide viewport
    900      */
    901     public synchronized void setUseWideViewPort(boolean use) {
    902         if (mUseWideViewport != use) {
    903             mUseWideViewport = use;
    904             postSync();
    905         }
    906     }
    907 
    908     /**
    909      * @return True if the WebView is using a wide viewport
    910      */
    911     public synchronized boolean getUseWideViewPort() {
    912         return mUseWideViewport;
    913     }
    914 
    915     /**
    916      * Tell the WebView whether it supports multiple windows. TRUE means
    917      *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
    918      *         boolean, Message)} is implemented by the host application.
    919      */
    920     public synchronized void setSupportMultipleWindows(boolean support) {
    921         if (mSupportMultipleWindows != support) {
    922             mSupportMultipleWindows = support;
    923             postSync();
    924         }
    925     }
    926 
    927     /**
    928      * @return True if the WebView is supporting multiple windows. This means
    929      *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
    930      *         boolean, Message)} is implemented by the host application.
    931      */
    932     public synchronized boolean supportMultipleWindows() {
    933         return mSupportMultipleWindows;
    934     }
    935 
    936     /**
    937      * Set the underlying layout algorithm. This will cause a relayout of the
    938      * WebView.
    939      * @param l A LayoutAlgorithm enum specifying the algorithm to use.
    940      * @see WebSettings.LayoutAlgorithm
    941      */
    942     public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
    943         // XXX: This will only be affective if libwebcore was built with
    944         // ANDROID_LAYOUT defined.
    945         if (mLayoutAlgorithm != l) {
    946             mLayoutAlgorithm = l;
    947             postSync();
    948         }
    949     }
    950 
    951     /**
    952      * Return the current layout algorithm. The default is NARROW_COLUMNS.
    953      * @return LayoutAlgorithm enum value describing the layout algorithm
    954      *         being used.
    955      * @see WebSettings.LayoutAlgorithm
    956      */
    957     public synchronized LayoutAlgorithm getLayoutAlgorithm() {
    958         return mLayoutAlgorithm;
    959     }
    960 
    961     /**
    962      * Set the standard font family name.
    963      * @param font A font family name.
    964      */
    965     public synchronized void setStandardFontFamily(String font) {
    966         if (font != null && !font.equals(mStandardFontFamily)) {
    967             mStandardFontFamily = font;
    968             postSync();
    969         }
    970     }
    971 
    972     /**
    973      * Get the standard font family name. The default is "sans-serif".
    974      * @return The standard font family name as a string.
    975      */
    976     public synchronized String getStandardFontFamily() {
    977         return mStandardFontFamily;
    978     }
    979 
    980     /**
    981      * Set the fixed font family name.
    982      * @param font A font family name.
    983      */
    984     public synchronized void setFixedFontFamily(String font) {
    985         if (font != null && !font.equals(mFixedFontFamily)) {
    986             mFixedFontFamily = font;
    987             postSync();
    988         }
    989     }
    990 
    991     /**
    992      * Get the fixed font family name. The default is "monospace".
    993      * @return The fixed font family name as a string.
    994      */
    995     public synchronized String getFixedFontFamily() {
    996         return mFixedFontFamily;
    997     }
    998 
    999     /**
   1000      * Set the sans-serif font family name.
   1001      * @param font A font family name.
   1002      */
   1003     public synchronized void setSansSerifFontFamily(String font) {
   1004         if (font != null && !font.equals(mSansSerifFontFamily)) {
   1005             mSansSerifFontFamily = font;
   1006             postSync();
   1007         }
   1008     }
   1009 
   1010     /**
   1011      * Get the sans-serif font family name.
   1012      * @return The sans-serif font family name as a string.
   1013      */
   1014     public synchronized String getSansSerifFontFamily() {
   1015         return mSansSerifFontFamily;
   1016     }
   1017 
   1018     /**
   1019      * Set the serif font family name. The default is "sans-serif".
   1020      * @param font A font family name.
   1021      */
   1022     public synchronized void setSerifFontFamily(String font) {
   1023         if (font != null && !font.equals(mSerifFontFamily)) {
   1024             mSerifFontFamily = font;
   1025             postSync();
   1026         }
   1027     }
   1028 
   1029     /**
   1030      * Get the serif font family name. The default is "serif".
   1031      * @return The serif font family name as a string.
   1032      */
   1033     public synchronized String getSerifFontFamily() {
   1034         return mSerifFontFamily;
   1035     }
   1036 
   1037     /**
   1038      * Set the cursive font family name.
   1039      * @param font A font family name.
   1040      */
   1041     public synchronized void setCursiveFontFamily(String font) {
   1042         if (font != null && !font.equals(mCursiveFontFamily)) {
   1043             mCursiveFontFamily = font;
   1044             postSync();
   1045         }
   1046     }
   1047 
   1048     /**
   1049      * Get the cursive font family name. The default is "cursive".
   1050      * @return The cursive font family name as a string.
   1051      */
   1052     public synchronized String getCursiveFontFamily() {
   1053         return mCursiveFontFamily;
   1054     }
   1055 
   1056     /**
   1057      * Set the fantasy font family name.
   1058      * @param font A font family name.
   1059      */
   1060     public synchronized void setFantasyFontFamily(String font) {
   1061         if (font != null && !font.equals(mFantasyFontFamily)) {
   1062             mFantasyFontFamily = font;
   1063             postSync();
   1064         }
   1065     }
   1066 
   1067     /**
   1068      * Get the fantasy font family name. The default is "fantasy".
   1069      * @return The fantasy font family name as a string.
   1070      */
   1071     public synchronized String getFantasyFontFamily() {
   1072         return mFantasyFontFamily;
   1073     }
   1074 
   1075     /**
   1076      * Set the minimum font size.
   1077      * @param size A non-negative integer between 1 and 72.
   1078      * Any number outside the specified range will be pinned.
   1079      */
   1080     public synchronized void setMinimumFontSize(int size) {
   1081         size = pin(size);
   1082         if (mMinimumFontSize != size) {
   1083             mMinimumFontSize = size;
   1084             postSync();
   1085         }
   1086     }
   1087 
   1088     /**
   1089      * Get the minimum font size. The default is 8.
   1090      * @return A non-negative integer between 1 and 72.
   1091      */
   1092     public synchronized int getMinimumFontSize() {
   1093         return mMinimumFontSize;
   1094     }
   1095 
   1096     /**
   1097      * Set the minimum logical font size.
   1098      * @param size A non-negative integer between 1 and 72.
   1099      * Any number outside the specified range will be pinned.
   1100      */
   1101     public synchronized void setMinimumLogicalFontSize(int size) {
   1102         size = pin(size);
   1103         if (mMinimumLogicalFontSize != size) {
   1104             mMinimumLogicalFontSize = size;
   1105             postSync();
   1106         }
   1107     }
   1108 
   1109     /**
   1110      * Get the minimum logical font size. The default is 8.
   1111      * @return A non-negative integer between 1 and 72.
   1112      */
   1113     public synchronized int getMinimumLogicalFontSize() {
   1114         return mMinimumLogicalFontSize;
   1115     }
   1116 
   1117     /**
   1118      * Set the default font size.
   1119      * @param size A non-negative integer between 1 and 72.
   1120      * Any number outside the specified range will be pinned.
   1121      */
   1122     public synchronized void setDefaultFontSize(int size) {
   1123         size = pin(size);
   1124         if (mDefaultFontSize != size) {
   1125             mDefaultFontSize = size;
   1126             postSync();
   1127         }
   1128     }
   1129 
   1130     /**
   1131      * Get the default font size. The default is 16.
   1132      * @return A non-negative integer between 1 and 72.
   1133      */
   1134     public synchronized int getDefaultFontSize() {
   1135         return mDefaultFontSize;
   1136     }
   1137 
   1138     /**
   1139      * Set the default fixed font size.
   1140      * @param size A non-negative integer between 1 and 72.
   1141      * Any number outside the specified range will be pinned.
   1142      */
   1143     public synchronized void setDefaultFixedFontSize(int size) {
   1144         size = pin(size);
   1145         if (mDefaultFixedFontSize != size) {
   1146             mDefaultFixedFontSize = size;
   1147             postSync();
   1148         }
   1149     }
   1150 
   1151     /**
   1152      * Get the default fixed font size. The default is 16.
   1153      * @return A non-negative integer between 1 and 72.
   1154      */
   1155     public synchronized int getDefaultFixedFontSize() {
   1156         return mDefaultFixedFontSize;
   1157     }
   1158 
   1159     /**
   1160      * Set the number of pages cached by the WebKit for the history navigation.
   1161      * @param size A non-negative integer between 0 (no cache) and 20 (max).
   1162      * @hide
   1163      */
   1164     public synchronized void setPageCacheCapacity(int size) {
   1165         if (size < 0) size = 0;
   1166         if (size > 20) size = 20;
   1167         if (mPageCacheCapacity != size) {
   1168             mPageCacheCapacity = size;
   1169             postSync();
   1170         }
   1171     }
   1172 
   1173     /**
   1174      * Tell the WebView to load image resources automatically.
   1175      * @param flag True if the WebView should load images automatically.
   1176      */
   1177     public synchronized void setLoadsImagesAutomatically(boolean flag) {
   1178         if (mLoadsImagesAutomatically != flag) {
   1179             mLoadsImagesAutomatically = flag;
   1180             postSync();
   1181         }
   1182     }
   1183 
   1184     /**
   1185      * Return true if the WebView will load image resources automatically.
   1186      * The default is true.
   1187      * @return True if the WebView loads images automatically.
   1188      */
   1189     public synchronized boolean getLoadsImagesAutomatically() {
   1190         return mLoadsImagesAutomatically;
   1191     }
   1192 
   1193     /**
   1194      * Tell the WebView to block network images. This is only checked when
   1195      * {@link #getLoadsImagesAutomatically} is true. If you set the value to
   1196      * false, images will automatically be loaded. Use this api to reduce
   1197      * bandwidth only. Use {@link #setBlockNetworkLoads} if possible.
   1198      * @param flag True if the WebView should block network images.
   1199      * @see #setBlockNetworkLoads
   1200      */
   1201     public synchronized void setBlockNetworkImage(boolean flag) {
   1202         if (mBlockNetworkImage != flag) {
   1203             mBlockNetworkImage = flag;
   1204             postSync();
   1205         }
   1206     }
   1207 
   1208     /**
   1209      * Return true if the WebView will block network images. The default is
   1210      * false.
   1211      * @return True if the WebView blocks network images.
   1212      */
   1213     public synchronized boolean getBlockNetworkImage() {
   1214         return mBlockNetworkImage;
   1215     }
   1216 
   1217     /**
   1218      * Tell the WebView to block all network load requests. If you set the
   1219      * value to false, you must call {@link android.webkit.WebView#reload} to
   1220      * fetch remote resources. This flag supercedes the value passed to
   1221      * {@link #setBlockNetworkImage}.
   1222      * @param flag True if the WebView should block all network loads.
   1223      * @see android.webkit.WebView#reload
   1224      */
   1225     public synchronized void setBlockNetworkLoads(boolean flag) {
   1226         if (mBlockNetworkLoads != flag) {
   1227             mBlockNetworkLoads = flag;
   1228             verifyNetworkAccess();
   1229             postSync();
   1230         }
   1231     }
   1232 
   1233     /**
   1234      * Return true if the WebView will block all network loads. The default is
   1235      * false.
   1236      * @return True if the WebView blocks all network loads.
   1237      */
   1238     public synchronized boolean getBlockNetworkLoads() {
   1239         return mBlockNetworkLoads;
   1240     }
   1241 
   1242 
   1243     private void verifyNetworkAccess() {
   1244         if (!mBlockNetworkLoads) {
   1245             if (mContext.checkPermission("android.permission.INTERNET",
   1246                     android.os.Process.myPid(), android.os.Process.myUid()) !=
   1247                         PackageManager.PERMISSION_GRANTED) {
   1248                 throw new SecurityException
   1249                         ("Permission denied - " +
   1250                                 "application missing INTERNET permission");
   1251             }
   1252         }
   1253     }
   1254 
   1255     /**
   1256      * Tell the WebView to enable javascript execution.
   1257      * @param flag True if the WebView should execute javascript.
   1258      */
   1259     public synchronized void setJavaScriptEnabled(boolean flag) {
   1260         if (mJavaScriptEnabled != flag) {
   1261             mJavaScriptEnabled = flag;
   1262             postSync();
   1263         }
   1264     }
   1265 
   1266     /**
   1267      * Tell the WebView to use Skia's hardware accelerated rendering path
   1268      * @param flag True if the WebView should use Skia's hw-accel path
   1269      * @hide
   1270      */
   1271     public synchronized void setHardwareAccelSkiaEnabled(boolean flag) {
   1272         if (mHardwareAccelSkia != flag) {
   1273             mHardwareAccelSkia = flag;
   1274             postSync();
   1275         }
   1276     }
   1277 
   1278     /**
   1279      * @return True if the WebView is using hardware accelerated skia
   1280      * @hide
   1281      */
   1282     public synchronized boolean getHardwareAccelSkiaEnabled() {
   1283         return mHardwareAccelSkia;
   1284     }
   1285 
   1286     /**
   1287      * Tell the WebView to show the visual indicator
   1288      * @param flag True if the WebView should show the visual indicator
   1289      * @hide
   1290      */
   1291     public synchronized void setShowVisualIndicator(boolean flag) {
   1292         if (mShowVisualIndicator != flag) {
   1293             mShowVisualIndicator = flag;
   1294             postSync();
   1295         }
   1296     }
   1297 
   1298     /**
   1299      * @return True if the WebView is showing the visual indicator
   1300      * @hide
   1301      */
   1302     public synchronized boolean getShowVisualIndicator() {
   1303         return mShowVisualIndicator;
   1304     }
   1305 
   1306     /**
   1307      * Tell the WebView to enable plugins.
   1308      * @param flag True if the WebView should load plugins.
   1309      * @deprecated This method has been deprecated in favor of
   1310      *             {@link #setPluginState}
   1311      */
   1312     @Deprecated
   1313     public synchronized void setPluginsEnabled(boolean flag) {
   1314         setPluginState(flag ? PluginState.ON : PluginState.OFF);
   1315     }
   1316 
   1317     /**
   1318      * Tell the WebView to enable, disable, or have plugins on demand. On
   1319      * demand mode means that if a plugin exists that can handle the embedded
   1320      * content, a placeholder icon will be shown instead of the plugin. When
   1321      * the placeholder is clicked, the plugin will be enabled.
   1322      * @param state One of the PluginState values.
   1323      */
   1324     public synchronized void setPluginState(PluginState state) {
   1325         if (mPluginState != state) {
   1326             mPluginState = state;
   1327             postSync();
   1328         }
   1329     }
   1330 
   1331     /**
   1332      * Set a custom path to plugins used by the WebView. This method is
   1333      * obsolete since each plugin is now loaded from its own package.
   1334      * @param pluginsPath String path to the directory containing plugins.
   1335      * @deprecated This method is no longer used as plugins are loaded from
   1336      * their own APK via the system's package manager.
   1337      */
   1338     @Deprecated
   1339     public synchronized void setPluginsPath(String pluginsPath) {
   1340     }
   1341 
   1342     /**
   1343      * Set the path to where database storage API databases should be saved.
   1344      * Nota that the WebCore Database Tracker only allows the path to be set once.
   1345      * This will update WebCore when the Sync runs in the C++ side.
   1346      * @param databasePath String path to the directory where databases should
   1347      *     be saved. May be the empty string but should never be null.
   1348      */
   1349     public synchronized void setDatabasePath(String databasePath) {
   1350         if (databasePath != null && !mDatabasePathHasBeenSet) {
   1351             mDatabasePath = databasePath;
   1352             mDatabasePathHasBeenSet = true;
   1353             postSync();
   1354         }
   1355     }
   1356 
   1357     /**
   1358      * Set the path where the Geolocation permissions database should be saved.
   1359      * This will update WebCore when the Sync runs in the C++ side.
   1360      * @param databasePath String path to the directory where the Geolocation
   1361      *     permissions database should be saved. May be the empty string but
   1362      *     should never be null.
   1363      */
   1364     public synchronized void setGeolocationDatabasePath(String databasePath) {
   1365         if (databasePath != null
   1366                 && !databasePath.equals(mGeolocationDatabasePath)) {
   1367             mGeolocationDatabasePath = databasePath;
   1368             postSync();
   1369         }
   1370     }
   1371 
   1372     /**
   1373      * Tell the WebView to enable Application Caches API.
   1374      * @param flag True if the WebView should enable Application Caches.
   1375      */
   1376     public synchronized void setAppCacheEnabled(boolean flag) {
   1377         if (mAppCacheEnabled != flag) {
   1378             mAppCacheEnabled = flag;
   1379             postSync();
   1380         }
   1381     }
   1382 
   1383     /**
   1384      * Set a custom path to the Application Caches files. The client
   1385      * must ensure it exists before this call.
   1386      * @param appCachePath String path to the directory containing Application
   1387      * Caches files. The appCache path can be the empty string but should not
   1388      * be null. Passing null for this parameter will result in a no-op.
   1389      */
   1390     public synchronized void setAppCachePath(String appCachePath) {
   1391         if (appCachePath != null && !appCachePath.equals(mAppCachePath)) {
   1392             mAppCachePath = appCachePath;
   1393             postSync();
   1394         }
   1395     }
   1396 
   1397     /**
   1398      * Set the maximum size for the Application Caches content.
   1399      * @param appCacheMaxSize the maximum size in bytes.
   1400      */
   1401     public synchronized void setAppCacheMaxSize(long appCacheMaxSize) {
   1402         if (appCacheMaxSize != mAppCacheMaxSize) {
   1403             mAppCacheMaxSize = appCacheMaxSize;
   1404             postSync();
   1405         }
   1406     }
   1407 
   1408     /**
   1409      * Set whether the database storage API is enabled.
   1410      * @param flag boolean True if the WebView should use the database storage
   1411      *     API.
   1412      */
   1413     public synchronized void setDatabaseEnabled(boolean flag) {
   1414        if (mDatabaseEnabled != flag) {
   1415            mDatabaseEnabled = flag;
   1416            postSync();
   1417        }
   1418     }
   1419 
   1420     /**
   1421      * Set whether the DOM storage API is enabled.
   1422      * @param flag boolean True if the WebView should use the DOM storage
   1423      *     API.
   1424      */
   1425     public synchronized void setDomStorageEnabled(boolean flag) {
   1426        if (mDomStorageEnabled != flag) {
   1427            mDomStorageEnabled = flag;
   1428            postSync();
   1429        }
   1430     }
   1431 
   1432     /**
   1433      * Returns true if the DOM Storage API's are enabled.
   1434      * @return True if the DOM Storage API's are enabled.
   1435      */
   1436     public synchronized boolean getDomStorageEnabled() {
   1437        return mDomStorageEnabled;
   1438     }
   1439 
   1440     /**
   1441      * Return the path to where database storage API databases are saved for
   1442      * the current WebView.
   1443      * @return the String path to the database storage API databases.
   1444      */
   1445     public synchronized String getDatabasePath() {
   1446         return mDatabasePath;
   1447     }
   1448 
   1449     /**
   1450      * Returns true if database storage API is enabled.
   1451      * @return True if the database storage API is enabled.
   1452      */
   1453     public synchronized boolean getDatabaseEnabled() {
   1454         return mDatabaseEnabled;
   1455     }
   1456 
   1457     /**
   1458      * Tell the WebView to enable WebWorkers API.
   1459      * @param flag True if the WebView should enable WebWorkers.
   1460      * Note that this flag only affects V8. JSC does not have
   1461      * an equivalent setting.
   1462      * @hide pending api council approval
   1463      */
   1464     public synchronized void setWorkersEnabled(boolean flag) {
   1465         if (mWorkersEnabled != flag) {
   1466             mWorkersEnabled = flag;
   1467             postSync();
   1468         }
   1469     }
   1470 
   1471     /**
   1472      * Sets whether Geolocation is enabled.
   1473      * @param flag Whether Geolocation should be enabled.
   1474      */
   1475     public synchronized void setGeolocationEnabled(boolean flag) {
   1476         if (mGeolocationEnabled != flag) {
   1477             mGeolocationEnabled = flag;
   1478             postSync();
   1479         }
   1480     }
   1481 
   1482     /**
   1483      * Sets whether XSS Auditor is enabled.
   1484      * @param flag Whether XSS Auditor should be enabled.
   1485      * @hide Only used by LayoutTestController.
   1486      */
   1487     public synchronized void setXSSAuditorEnabled(boolean flag) {
   1488         if (mXSSAuditorEnabled != flag) {
   1489             mXSSAuditorEnabled = flag;
   1490             postSync();
   1491         }
   1492     }
   1493 
   1494     /**
   1495      * Return true if javascript is enabled. <b>Note: The default is false.</b>
   1496      * @return True if javascript is enabled.
   1497      */
   1498     public synchronized boolean getJavaScriptEnabled() {
   1499         return mJavaScriptEnabled;
   1500     }
   1501 
   1502     /**
   1503      * Return true if plugins are enabled.
   1504      * @return True if plugins are enabled.
   1505      * @deprecated This method has been replaced by {@link #getPluginState}
   1506      */
   1507     @Deprecated
   1508     public synchronized boolean getPluginsEnabled() {
   1509         return mPluginState == PluginState.ON;
   1510     }
   1511 
   1512     /**
   1513      * Return the current plugin state.
   1514      * @return A value corresponding to the enum PluginState.
   1515      */
   1516     public synchronized PluginState getPluginState() {
   1517         return mPluginState;
   1518     }
   1519 
   1520     /**
   1521      * Returns the directory that contains the plugin libraries. This method is
   1522      * obsolete since each plugin is now loaded from its own package.
   1523      * @return An empty string.
   1524      * @deprecated This method is no longer used as plugins are loaded from
   1525      * their own APK via the system's package manager.
   1526      */
   1527     @Deprecated
   1528     public synchronized String getPluginsPath() {
   1529         return "";
   1530     }
   1531 
   1532     /**
   1533      * Tell javascript to open windows automatically. This applies to the
   1534      * javascript function window.open().
   1535      * @param flag True if javascript can open windows automatically.
   1536      */
   1537     public synchronized void setJavaScriptCanOpenWindowsAutomatically(
   1538             boolean flag) {
   1539         if (mJavaScriptCanOpenWindowsAutomatically != flag) {
   1540             mJavaScriptCanOpenWindowsAutomatically = flag;
   1541             postSync();
   1542         }
   1543     }
   1544 
   1545     /**
   1546      * Return true if javascript can open windows automatically. The default
   1547      * is false.
   1548      * @return True if javascript can open windows automatically during
   1549      *         window.open().
   1550      */
   1551     public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() {
   1552         return mJavaScriptCanOpenWindowsAutomatically;
   1553     }
   1554 
   1555     /**
   1556      * Set the default text encoding name to use when decoding html pages.
   1557      * @param encoding The text encoding name.
   1558      */
   1559     public synchronized void setDefaultTextEncodingName(String encoding) {
   1560         if (encoding != null && !encoding.equals(mDefaultTextEncoding)) {
   1561             mDefaultTextEncoding = encoding;
   1562             postSync();
   1563         }
   1564     }
   1565 
   1566     /**
   1567      * Get the default text encoding name. The default is "Latin-1".
   1568      * @return The default text encoding name as a string.
   1569      */
   1570     public synchronized String getDefaultTextEncodingName() {
   1571         return mDefaultTextEncoding;
   1572     }
   1573 
   1574     /**
   1575      * Set the WebView's user-agent string. If the string "ua" is null or empty,
   1576      * it will use the system default user-agent string.
   1577      */
   1578     public synchronized void setUserAgentString(String ua) {
   1579         if (ua == null || ua.length() == 0) {
   1580             synchronized(sLockForLocaleSettings) {
   1581                 Locale currentLocale = Locale.getDefault();
   1582                 if (!sLocale.equals(currentLocale)) {
   1583                     sLocale = currentLocale;
   1584                     mAcceptLanguage = getCurrentAcceptLanguage();
   1585                 }
   1586             }
   1587             ua = getCurrentUserAgent();
   1588             mUseDefaultUserAgent = true;
   1589         } else  {
   1590             mUseDefaultUserAgent = false;
   1591         }
   1592 
   1593         if (!ua.equals(mUserAgent)) {
   1594             mUserAgent = ua;
   1595             postSync();
   1596         }
   1597     }
   1598 
   1599     /**
   1600      * Return the WebView's user-agent string.
   1601      */
   1602     public synchronized String getUserAgentString() {
   1603         if (DESKTOP_USERAGENT.equals(mUserAgent) ||
   1604                 IPHONE_USERAGENT.equals(mUserAgent) ||
   1605                 !mUseDefaultUserAgent) {
   1606             return mUserAgent;
   1607         }
   1608 
   1609         boolean doPostSync = false;
   1610         synchronized(sLockForLocaleSettings) {
   1611             Locale currentLocale = Locale.getDefault();
   1612             if (!sLocale.equals(currentLocale)) {
   1613                 sLocale = currentLocale;
   1614                 mUserAgent = getCurrentUserAgent();
   1615                 mAcceptLanguage = getCurrentAcceptLanguage();
   1616                 doPostSync = true;
   1617             }
   1618         }
   1619         if (doPostSync) {
   1620             postSync();
   1621         }
   1622         return mUserAgent;
   1623     }
   1624 
   1625     /* package api to grab the Accept Language string. */
   1626     /*package*/ synchronized String getAcceptLanguage() {
   1627         synchronized(sLockForLocaleSettings) {
   1628             Locale currentLocale = Locale.getDefault();
   1629             if (!sLocale.equals(currentLocale)) {
   1630                 sLocale = currentLocale;
   1631                 mAcceptLanguage = getCurrentAcceptLanguage();
   1632             }
   1633         }
   1634         return mAcceptLanguage;
   1635     }
   1636 
   1637     /* package */ boolean isNarrowColumnLayout() {
   1638         return getLayoutAlgorithm() == LayoutAlgorithm.NARROW_COLUMNS;
   1639     }
   1640 
   1641     /**
   1642      * Tell the WebView whether it needs to set a node to have focus when
   1643      * {@link WebView#requestFocus(int, android.graphics.Rect)} is called.
   1644      *
   1645      * @param flag
   1646      */
   1647     public void setNeedInitialFocus(boolean flag) {
   1648         if (mNeedInitialFocus != flag) {
   1649             mNeedInitialFocus = flag;
   1650         }
   1651     }
   1652 
   1653     /* Package api to get the choice whether it needs to set initial focus. */
   1654     /* package */ boolean getNeedInitialFocus() {
   1655         return mNeedInitialFocus;
   1656     }
   1657 
   1658     /**
   1659      * Set the priority of the Render thread. Unlike the other settings, this
   1660      * one only needs to be called once per process. The default is NORMAL.
   1661      *
   1662      * @param priority RenderPriority, can be normal, high or low.
   1663      */
   1664     public synchronized void setRenderPriority(RenderPriority priority) {
   1665         if (mRenderPriority != priority) {
   1666             mRenderPriority = priority;
   1667             mEventHandler.sendMessage(Message.obtain(null,
   1668                     EventHandler.PRIORITY));
   1669         }
   1670     }
   1671 
   1672     /**
   1673      * Override the way the cache is used. The way the cache is used is based
   1674      * on the navigation option. For a normal page load, the cache is checked
   1675      * and content is re-validated as needed. When navigating back, content is
   1676      * not revalidated, instead the content is just pulled from the cache.
   1677      * This function allows the client to override this behavior.
   1678      * @param mode One of the LOAD_ values.
   1679      */
   1680     public void setCacheMode(int mode) {
   1681         if (mode != mOverrideCacheMode) {
   1682             mOverrideCacheMode = mode;
   1683             postSync();
   1684         }
   1685     }
   1686 
   1687     /**
   1688      * Return the current setting for overriding the cache mode. For a full
   1689      * description, see the {@link #setCacheMode(int)} function.
   1690      */
   1691     public int getCacheMode() {
   1692         return mOverrideCacheMode;
   1693     }
   1694 
   1695     /**
   1696      * If set, webkit alternately shrinks and expands images viewed outside
   1697      * of an HTML page to fit the screen. This conflicts with attempts by
   1698      * the UI to zoom in and out of an image, so it is set false by default.
   1699      * @param shrink Set true to let webkit shrink the standalone image to fit.
   1700      * {@hide}
   1701      */
   1702     public void setShrinksStandaloneImagesToFit(boolean shrink) {
   1703         if (mShrinksStandaloneImagesToFit != shrink) {
   1704             mShrinksStandaloneImagesToFit = shrink;
   1705             postSync();
   1706         }
   1707      }
   1708 
   1709     /**
   1710      * Specify the maximum decoded image size. The default is
   1711      * 2 megs for small memory devices and 8 megs for large memory devices.
   1712      * @param size The maximum decoded size, or zero to set to the default.
   1713      * @hide pending api council approval
   1714      */
   1715     public void setMaximumDecodedImageSize(long size) {
   1716         if (mMaximumDecodedImageSize != size) {
   1717             mMaximumDecodedImageSize = size;
   1718             postSync();
   1719         }
   1720     }
   1721 
   1722     /**
   1723      * Returns whether to use fixed viewport.  Use fixed viewport
   1724      * whenever wide viewport is on.
   1725      */
   1726     /* package */ boolean getUseFixedViewport() {
   1727         return getUseWideViewPort();
   1728     }
   1729 
   1730     /**
   1731      * Returns whether private browsing is enabled.
   1732      */
   1733     /* package */ boolean isPrivateBrowsingEnabled() {
   1734         return mPrivateBrowsingEnabled;
   1735     }
   1736 
   1737     /**
   1738      * Sets whether private browsing is enabled.
   1739      * @param flag Whether private browsing should be enabled.
   1740      */
   1741     /* package */ synchronized void setPrivateBrowsingEnabled(boolean flag) {
   1742         if (mPrivateBrowsingEnabled != flag) {
   1743             mPrivateBrowsingEnabled = flag;
   1744 
   1745             // AutoFill is dependant on private browsing being enabled so
   1746             // reset it to take account of the new value of mPrivateBrowsingEnabled.
   1747             setAutoFillEnabled(mAutoFillEnabled);
   1748 
   1749             postSync();
   1750         }
   1751     }
   1752 
   1753     /**
   1754      * Returns whether the viewport metatag can disable zooming
   1755      * @hide
   1756      */
   1757     public boolean forceUserScalable() {
   1758         return mForceUserScalable;
   1759     }
   1760 
   1761     /**
   1762      * Sets whether viewport metatag can disable zooming.
   1763      * @param flag Whether or not to forceably enable user scalable.
   1764      * @hide
   1765      */
   1766     public synchronized void setForceUserScalable(boolean flag) {
   1767         mForceUserScalable = flag;
   1768     }
   1769 
   1770     synchronized void setSyntheticLinksEnabled(boolean flag) {
   1771         if (mSyntheticLinksEnabled != flag) {
   1772             mSyntheticLinksEnabled = flag;
   1773             postSync();
   1774         }
   1775     }
   1776 
   1777     /**
   1778      * @hide
   1779      */
   1780     public synchronized void setAutoFillEnabled(boolean enabled) {
   1781         // AutoFill is always disabled in private browsing mode.
   1782         boolean autoFillEnabled = enabled && !mPrivateBrowsingEnabled;
   1783         if (mAutoFillEnabled != autoFillEnabled) {
   1784             mAutoFillEnabled = autoFillEnabled;
   1785             postSync();
   1786         }
   1787     }
   1788 
   1789     /**
   1790      * @hide
   1791      */
   1792     public synchronized boolean getAutoFillEnabled() {
   1793         return mAutoFillEnabled;
   1794     }
   1795 
   1796     /**
   1797      * @hide
   1798      */
   1799     public synchronized void setAutoFillProfile(AutoFillProfile profile) {
   1800         if (mAutoFillProfile != profile) {
   1801             mAutoFillProfile = profile;
   1802             postSync();
   1803         }
   1804     }
   1805 
   1806     /**
   1807      * @hide
   1808      */
   1809     public synchronized AutoFillProfile getAutoFillProfile() {
   1810         return mAutoFillProfile;
   1811     }
   1812 
   1813     int getDoubleTapToastCount() {
   1814         return mDoubleTapToastCount;
   1815     }
   1816 
   1817     void setDoubleTapToastCount(int count) {
   1818         if (mDoubleTapToastCount != count) {
   1819             mDoubleTapToastCount = count;
   1820             // write the settings in the non-UI thread
   1821             mEventHandler.sendMessage(Message.obtain(null,
   1822                     EventHandler.SET_DOUBLE_TAP_TOAST_COUNT));
   1823         }
   1824     }
   1825 
   1826     /**
   1827      * @hide
   1828      */
   1829     public void setProperty(String key, String value) {
   1830         if (mWebView.nativeSetProperty(key, value)) {
   1831             mWebView.contentInvalidateAll();
   1832         }
   1833     }
   1834 
   1835     /**
   1836      * @hide
   1837      */
   1838     public String getProperty(String key) {
   1839         return mWebView.nativeGetProperty(key);
   1840     }
   1841 
   1842     /**
   1843      * Transfer messages from the queue to the new WebCoreThread. Called from
   1844      * WebCore thread.
   1845      */
   1846     /*package*/
   1847     synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
   1848         mBrowserFrame = frame;
   1849         if (DebugFlags.WEB_SETTINGS) {
   1850             junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
   1851         }
   1852 
   1853         SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE,
   1854                 Context.MODE_PRIVATE);
   1855         if (mDoubleTapToastCount > 0) {
   1856             mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
   1857                     mDoubleTapToastCount);
   1858         }
   1859         nativeSync(frame.mNativeFrame);
   1860         mSyncPending = false;
   1861         mEventHandler.createHandler();
   1862     }
   1863 
   1864     /**
   1865      * Let the Settings object know that our owner is being destroyed.
   1866      */
   1867     /*package*/
   1868     synchronized void onDestroyed() {
   1869     }
   1870 
   1871     private int pin(int size) {
   1872         // FIXME: 72 is just an arbitrary max text size value.
   1873         if (size < 1) {
   1874             return 1;
   1875         } else if (size > 72) {
   1876             return 72;
   1877         }
   1878         return size;
   1879     }
   1880 
   1881     /* Post a SYNC message to handle syncing the native settings. */
   1882     private synchronized void postSync() {
   1883         // Only post if a sync is not pending
   1884         if (!mSyncPending) {
   1885             mSyncPending = mEventHandler.sendMessage(
   1886                     Message.obtain(null, EventHandler.SYNC));
   1887         }
   1888     }
   1889 
   1890     // Synchronize the native and java settings.
   1891     private native void nativeSync(int nativeFrame);
   1892 }
   1893