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