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