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