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            mWebView.updateJavaScriptEnabled(flag);
1126        }
1127    }
1128
1129    /**
1130     * @see android.webkit.WebSettings#setAllowUniversalAccessFromFileURLs
1131     */
1132    @Override
1133    public synchronized void setAllowUniversalAccessFromFileURLs(boolean flag) {
1134        if (mAllowUniversalAccessFromFileURLs != flag) {
1135            mAllowUniversalAccessFromFileURLs = flag;
1136            postSync();
1137        }
1138    }
1139
1140    /**
1141     * @see android.webkit.WebSettings#setAllowFileAccessFromFileURLs
1142     */
1143    @Override
1144    public synchronized void setAllowFileAccessFromFileURLs(boolean flag) {
1145        if (mAllowFileAccessFromFileURLs != flag) {
1146            mAllowFileAccessFromFileURLs = flag;
1147            postSync();
1148        }
1149    }
1150
1151    /**
1152     * Tell the WebView to use Skia's hardware accelerated rendering path
1153     * @param flag True if the WebView should use Skia's hw-accel path
1154     */
1155    public synchronized void setHardwareAccelSkiaEnabled(boolean flag) {
1156        if (mHardwareAccelSkia != flag) {
1157            mHardwareAccelSkia = flag;
1158            postSync();
1159        }
1160    }
1161
1162    /**
1163     * @return True if the WebView is using hardware accelerated skia
1164     */
1165    public synchronized boolean getHardwareAccelSkiaEnabled() {
1166        return mHardwareAccelSkia;
1167    }
1168
1169    /**
1170     * Tell the WebView to show the visual indicator
1171     * @param flag True if the WebView should show the visual indicator
1172     */
1173    public synchronized void setShowVisualIndicator(boolean flag) {
1174        if (mShowVisualIndicator != flag) {
1175            mShowVisualIndicator = flag;
1176            postSync();
1177        }
1178    }
1179
1180    /**
1181     * @return True if the WebView is showing the visual indicator
1182     */
1183    public synchronized boolean getShowVisualIndicator() {
1184        return mShowVisualIndicator;
1185    }
1186
1187    /**
1188     * @see android.webkit.WebSettings#setPluginsEnabled(boolean)
1189     */
1190    @Override
1191    @Deprecated
1192    public synchronized void setPluginsEnabled(boolean flag) {
1193        setPluginState(flag ? PluginState.ON : PluginState.OFF);
1194    }
1195
1196    /**
1197     * @see android.webkit.WebSettings#setPluginState(android.webkit.WebSettingsClassic.PluginState)
1198     */
1199    @Override
1200    public synchronized void setPluginState(PluginState state) {
1201        if (mPluginState != state) {
1202            mPluginState = state;
1203            postSync();
1204        }
1205    }
1206
1207    /**
1208     * @see android.webkit.WebSettings#setPluginsPath(java.lang.String)
1209     */
1210    @Override
1211    @Deprecated
1212    public synchronized void setPluginsPath(String pluginsPath) {
1213    }
1214
1215    /**
1216     * @see android.webkit.WebSettings#setDatabasePath(java.lang.String)
1217     */
1218    @Override
1219    public synchronized void setDatabasePath(String databasePath) {
1220        if (databasePath != null && !mDatabasePathHasBeenSet) {
1221            mDatabasePath = databasePath;
1222            mDatabasePathHasBeenSet = true;
1223            postSync();
1224        }
1225    }
1226
1227    /**
1228     * @see android.webkit.WebSettings#setGeolocationDatabasePath(java.lang.String)
1229     */
1230    @Override
1231    public synchronized void setGeolocationDatabasePath(String databasePath) {
1232        if (databasePath != null
1233                && !databasePath.equals(mGeolocationDatabasePath)) {
1234            mGeolocationDatabasePath = databasePath;
1235            postSync();
1236        }
1237    }
1238
1239    /**
1240     * @see android.webkit.WebSettings#setAppCacheEnabled(boolean)
1241     */
1242    @Override
1243    public synchronized void setAppCacheEnabled(boolean flag) {
1244        if (mAppCacheEnabled != flag) {
1245            mAppCacheEnabled = flag;
1246            postSync();
1247        }
1248    }
1249
1250    /**
1251     * @see android.webkit.WebSettings#setAppCachePath(java.lang.String)
1252     */
1253    @Override
1254    public synchronized void setAppCachePath(String path) {
1255        // We test for a valid path and for repeated setting on the native
1256        // side, but we can avoid syncing in some simple cases.
1257        if (mAppCachePath == null && path != null && !path.isEmpty()) {
1258            mAppCachePath = path;
1259            postSync();
1260        }
1261    }
1262
1263    /**
1264     * @see android.webkit.WebSettings#setAppCacheMaxSize(long)
1265     */
1266    @Override
1267    public synchronized void setAppCacheMaxSize(long appCacheMaxSize) {
1268        if (appCacheMaxSize != mAppCacheMaxSize) {
1269            mAppCacheMaxSize = appCacheMaxSize;
1270            postSync();
1271        }
1272    }
1273
1274    /**
1275     * @see android.webkit.WebSettings#setDatabaseEnabled(boolean)
1276     */
1277    @Override
1278    public synchronized void setDatabaseEnabled(boolean flag) {
1279       if (mDatabaseEnabled != flag) {
1280           mDatabaseEnabled = flag;
1281           postSync();
1282       }
1283    }
1284
1285    /**
1286     * @see android.webkit.WebSettings#setDomStorageEnabled(boolean)
1287     */
1288    @Override
1289    public synchronized void setDomStorageEnabled(boolean flag) {
1290       if (mDomStorageEnabled != flag) {
1291           mDomStorageEnabled = flag;
1292           postSync();
1293       }
1294    }
1295
1296    /**
1297     * @see android.webkit.WebSettings#getDomStorageEnabled()
1298     */
1299    @Override
1300    public synchronized boolean getDomStorageEnabled() {
1301       return mDomStorageEnabled;
1302    }
1303
1304    /**
1305     * @see android.webkit.WebSettings#getDatabasePath()
1306     */
1307    @Override
1308    public synchronized String getDatabasePath() {
1309        return mDatabasePath;
1310    }
1311
1312    /**
1313     * @see android.webkit.WebSettings#getDatabaseEnabled()
1314     */
1315    @Override
1316    public synchronized boolean getDatabaseEnabled() {
1317        return mDatabaseEnabled;
1318    }
1319
1320    /**
1321     * Tell the WebView to enable WebWorkers API.
1322     * @param flag True if the WebView should enable WebWorkers.
1323     * Note that this flag only affects V8. JSC does not have
1324     * an equivalent setting.
1325     */
1326    public synchronized void setWorkersEnabled(boolean flag) {
1327        if (mWorkersEnabled != flag) {
1328            mWorkersEnabled = flag;
1329            postSync();
1330        }
1331    }
1332
1333    /**
1334     * @see android.webkit.WebSettings#setGeolocationEnabled(boolean)
1335     */
1336    @Override
1337    public synchronized void setGeolocationEnabled(boolean flag) {
1338        if (mGeolocationEnabled != flag) {
1339            mGeolocationEnabled = flag;
1340            postSync();
1341        }
1342    }
1343
1344    /**
1345     * Sets whether XSS Auditor is enabled.
1346     * Only used by LayoutTestController.
1347     * @param flag Whether XSS Auditor should be enabled.
1348     */
1349    public synchronized void setXSSAuditorEnabled(boolean flag) {
1350        if (mXSSAuditorEnabled != flag) {
1351            mXSSAuditorEnabled = flag;
1352            postSync();
1353        }
1354    }
1355
1356    /**
1357     * Enables/disables HTML5 link "prefetch" parameter.
1358     */
1359    public synchronized void setLinkPrefetchEnabled(boolean flag) {
1360        if (mLinkPrefetchEnabled != flag) {
1361            mLinkPrefetchEnabled = flag;
1362            postSync();
1363        }
1364    }
1365
1366    /**
1367     * @see android.webkit.WebSettings#getJavaScriptEnabled()
1368     */
1369    @Override
1370    public synchronized boolean getJavaScriptEnabled() {
1371        return mJavaScriptEnabled;
1372    }
1373
1374    /**
1375     * @see android.webkit.WebSettings#getAllowUniversalFileAccessFromFileURLs
1376     */
1377    @Override
1378    public synchronized boolean getAllowUniversalAccessFromFileURLs() {
1379        return mAllowUniversalAccessFromFileURLs;
1380    }
1381
1382    /**
1383     * @see android.webkit.WebSettings#getAllowFileAccessFromFileURLs
1384     */
1385    @Override
1386    public synchronized boolean getAllowFileAccessFromFileURLs() {
1387        return mAllowFileAccessFromFileURLs;
1388    }
1389
1390    /**
1391     * @see android.webkit.WebSettings#getPluginsEnabled()
1392     */
1393    @Override
1394    @Deprecated
1395    public synchronized boolean getPluginsEnabled() {
1396        return mPluginState == PluginState.ON;
1397    }
1398
1399    /**
1400     * @see android.webkit.WebSettings#getPluginState()
1401     */
1402    @Override
1403    public synchronized PluginState getPluginState() {
1404        return mPluginState;
1405    }
1406
1407    /**
1408     * @see android.webkit.WebSettings#getPluginsPath()
1409     */
1410    @Override
1411    @Deprecated
1412    public synchronized String getPluginsPath() {
1413        return "";
1414    }
1415
1416    /**
1417     * @see android.webkit.WebSettings#setJavaScriptCanOpenWindowsAutomatically(boolean)
1418     */
1419    @Override
1420    public synchronized void setJavaScriptCanOpenWindowsAutomatically(
1421            boolean flag) {
1422        if (mJavaScriptCanOpenWindowsAutomatically != flag) {
1423            mJavaScriptCanOpenWindowsAutomatically = flag;
1424            postSync();
1425        }
1426    }
1427
1428    /**
1429     * @see android.webkit.WebSettings#getJavaScriptCanOpenWindowsAutomatically()
1430     */
1431    @Override
1432    public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() {
1433        return mJavaScriptCanOpenWindowsAutomatically;
1434    }
1435
1436    /**
1437     * @see android.webkit.WebSettings#setDefaultTextEncodingName(java.lang.String)
1438     */
1439    @Override
1440    public synchronized void setDefaultTextEncodingName(String encoding) {
1441        if (encoding != null && !encoding.equals(mDefaultTextEncoding)) {
1442            mDefaultTextEncoding = encoding;
1443            postSync();
1444        }
1445    }
1446
1447    /**
1448     * @see android.webkit.WebSettings#getDefaultTextEncodingName()
1449     */
1450    @Override
1451    public synchronized String getDefaultTextEncodingName() {
1452        return mDefaultTextEncoding;
1453    }
1454
1455    /**
1456     * @see android.webkit.WebSettings#setUserAgentString(java.lang.String)
1457     */
1458    @Override
1459    public synchronized void setUserAgentString(String ua) {
1460        if (ua == null || ua.length() == 0) {
1461            synchronized(sLockForLocaleSettings) {
1462                Locale currentLocale = Locale.getDefault();
1463                if (!sLocale.equals(currentLocale)) {
1464                    sLocale = currentLocale;
1465                    mAcceptLanguage = getCurrentAcceptLanguage();
1466                }
1467            }
1468            ua = getCurrentUserAgent();
1469            mUseDefaultUserAgent = true;
1470        } else  {
1471            mUseDefaultUserAgent = false;
1472        }
1473
1474        if (!ua.equals(mUserAgent)) {
1475            mUserAgent = ua;
1476            postSync();
1477        }
1478    }
1479
1480    /**
1481     * @see android.webkit.WebSettings#getUserAgentString()
1482     */
1483    @Override
1484    public synchronized String getUserAgentString() {
1485        if (DESKTOP_USERAGENT.equals(mUserAgent) ||
1486                IPHONE_USERAGENT.equals(mUserAgent) ||
1487                !mUseDefaultUserAgent) {
1488            return mUserAgent;
1489        }
1490
1491        boolean doPostSync = false;
1492        synchronized(sLockForLocaleSettings) {
1493            Locale currentLocale = Locale.getDefault();
1494            if (!sLocale.equals(currentLocale)) {
1495                sLocale = currentLocale;
1496                mUserAgent = getCurrentUserAgent();
1497                mAcceptLanguage = getCurrentAcceptLanguage();
1498                doPostSync = true;
1499            }
1500        }
1501        if (doPostSync) {
1502            postSync();
1503        }
1504        return mUserAgent;
1505    }
1506
1507    /* package api to grab the Accept Language string. */
1508    /*package*/ synchronized String getAcceptLanguage() {
1509        synchronized(sLockForLocaleSettings) {
1510            Locale currentLocale = Locale.getDefault();
1511            if (!sLocale.equals(currentLocale)) {
1512                sLocale = currentLocale;
1513                mAcceptLanguage = getCurrentAcceptLanguage();
1514            }
1515        }
1516        return mAcceptLanguage;
1517    }
1518
1519    /* package */ boolean isNarrowColumnLayout() {
1520        return getLayoutAlgorithm() == LayoutAlgorithm.NARROW_COLUMNS;
1521    }
1522
1523    /**
1524     * @see android.webkit.WebSettings#setNeedInitialFocus(boolean)
1525     */
1526    @Override
1527    public void setNeedInitialFocus(boolean flag) {
1528        if (mNeedInitialFocus != flag) {
1529            mNeedInitialFocus = flag;
1530        }
1531    }
1532
1533    /* Package api to get the choice whether it needs to set initial focus. */
1534    /* package */ boolean getNeedInitialFocus() {
1535        return mNeedInitialFocus;
1536    }
1537
1538    /**
1539     * @see android.webkit.WebSettings#setRenderPriority(android.webkit.WebSettingsClassic.RenderPriority)
1540     */
1541    @Override
1542    public synchronized void setRenderPriority(RenderPriority priority) {
1543        if (mRenderPriority != priority) {
1544            mRenderPriority = priority;
1545            mEventHandler.sendMessage(Message.obtain(null,
1546                    EventHandler.PRIORITY));
1547        }
1548    }
1549
1550    /**
1551     * @see android.webkit.WebSettings#setCacheMode(int)
1552     */
1553    @Override
1554    public void setCacheMode(int mode) {
1555        if (mode != mOverrideCacheMode) {
1556            mOverrideCacheMode = mode;
1557            postSync();
1558        }
1559    }
1560
1561    /**
1562     * @see android.webkit.WebSettings#getCacheMode()
1563     */
1564    @Override
1565    public int getCacheMode() {
1566        return mOverrideCacheMode;
1567    }
1568
1569    /**
1570     * If set, webkit alternately shrinks and expands images viewed outside
1571     * of an HTML page to fit the screen. This conflicts with attempts by
1572     * the UI to zoom in and out of an image, so it is set false by default.
1573     * @param shrink Set true to let webkit shrink the standalone image to fit.
1574     */
1575    public void setShrinksStandaloneImagesToFit(boolean shrink) {
1576        if (mShrinksStandaloneImagesToFit != shrink) {
1577            mShrinksStandaloneImagesToFit = shrink;
1578            postSync();
1579        }
1580     }
1581
1582    /**
1583     * Specify the maximum decoded image size. The default is
1584     * 2 megs for small memory devices and 8 megs for large memory devices.
1585     * @param size The maximum decoded size, or zero to set to the default.
1586     */
1587    public void setMaximumDecodedImageSize(long size) {
1588        if (mMaximumDecodedImageSize != size) {
1589            mMaximumDecodedImageSize = size;
1590            postSync();
1591        }
1592    }
1593
1594    /**
1595     * Returns whether to use fixed viewport.  Use fixed viewport
1596     * whenever wide viewport is on.
1597     */
1598    /* package */ boolean getUseFixedViewport() {
1599        return getUseWideViewPort();
1600    }
1601
1602    /**
1603     * Returns whether private browsing is enabled.
1604     */
1605    /* package */ boolean isPrivateBrowsingEnabled() {
1606        return mPrivateBrowsingEnabled;
1607    }
1608
1609    /**
1610     * Sets whether private browsing is enabled.
1611     * @param flag Whether private browsing should be enabled.
1612     */
1613    /* package */ synchronized void setPrivateBrowsingEnabled(boolean flag) {
1614        if (mPrivateBrowsingEnabled != flag) {
1615            mPrivateBrowsingEnabled = flag;
1616
1617            // AutoFill is dependant on private browsing being enabled so
1618            // reset it to take account of the new value of mPrivateBrowsingEnabled.
1619            setAutoFillEnabled(mAutoFillEnabled);
1620
1621            postSync();
1622        }
1623    }
1624
1625    /**
1626     * Returns whether the viewport metatag can disable zooming
1627     */
1628    public boolean forceUserScalable() {
1629        return mForceUserScalable;
1630    }
1631
1632    /**
1633     * Sets whether viewport metatag can disable zooming.
1634     * @param flag Whether or not to forceably enable user scalable.
1635     */
1636    public synchronized void setForceUserScalable(boolean flag) {
1637        mForceUserScalable = flag;
1638    }
1639
1640    synchronized void setSyntheticLinksEnabled(boolean flag) {
1641        if (mSyntheticLinksEnabled != flag) {
1642            mSyntheticLinksEnabled = flag;
1643            postSync();
1644        }
1645    }
1646
1647    public synchronized void setAutoFillEnabled(boolean enabled) {
1648        // AutoFill is always disabled in private browsing mode.
1649        boolean autoFillEnabled = enabled && !mPrivateBrowsingEnabled;
1650        if (mAutoFillEnabled != autoFillEnabled) {
1651            mAutoFillEnabled = autoFillEnabled;
1652            postSync();
1653        }
1654    }
1655
1656    public synchronized boolean getAutoFillEnabled() {
1657        return mAutoFillEnabled;
1658    }
1659
1660    public synchronized void setAutoFillProfile(AutoFillProfile profile) {
1661        if (mAutoFillProfile != profile) {
1662            mAutoFillProfile = profile;
1663            postSync();
1664        }
1665    }
1666
1667    public synchronized AutoFillProfile getAutoFillProfile() {
1668        return mAutoFillProfile;
1669    }
1670
1671    int getDoubleTapToastCount() {
1672        return mDoubleTapToastCount;
1673    }
1674
1675    void setDoubleTapToastCount(int count) {
1676        if (mDoubleTapToastCount != count) {
1677            mDoubleTapToastCount = count;
1678            // write the settings in the non-UI thread
1679            mEventHandler.sendMessage(Message.obtain(null,
1680                    EventHandler.SET_DOUBLE_TAP_TOAST_COUNT));
1681        }
1682    }
1683
1684    public void setProperty(String key, String value) {
1685        if (mWebView.nativeSetProperty(key, value)) {
1686            mWebView.invalidate();
1687        }
1688    }
1689
1690    public String getProperty(String key) {
1691        return mWebView.nativeGetProperty(key);
1692    }
1693
1694    /**
1695     * Transfer messages from the queue to the new WebCoreThread. Called from
1696     * WebCore thread.
1697     */
1698    /*package*/
1699    synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
1700        mBrowserFrame = frame;
1701        if (DebugFlags.WEB_SETTINGS) {
1702            junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
1703        }
1704
1705        SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE,
1706                Context.MODE_PRIVATE);
1707        if (mDoubleTapToastCount > 0) {
1708            mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
1709                    mDoubleTapToastCount);
1710        }
1711        nativeSync(frame.mNativeFrame);
1712        mSyncPending = false;
1713        mEventHandler.createHandler();
1714    }
1715
1716    /**
1717     * Let the Settings object know that our owner is being destroyed.
1718     */
1719    /*package*/
1720    synchronized void onDestroyed() {
1721    }
1722
1723    private int pin(int size) {
1724        // FIXME: 72 is just an arbitrary max text size value.
1725        if (size < 1) {
1726            return 1;
1727        } else if (size > 72) {
1728            return 72;
1729        }
1730        return size;
1731    }
1732
1733    /* Post a SYNC message to handle syncing the native settings. */
1734    private synchronized void postSync() {
1735        // Only post if a sync is not pending
1736        if (!mSyncPending) {
1737            mSyncPending = mEventHandler.sendMessage(
1738                    Message.obtain(null, EventHandler.SYNC));
1739        }
1740    }
1741
1742    // Synchronize the native and java settings.
1743    private native void nativeSync(int nativeFrame);
1744}
1745