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