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