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