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