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