WebSettings.java revision 34e9f249a9b36ebe64476b997bca0edf990fbc0d
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 TextSize        mTextSize = TextSize.NORMAL;
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         mUseFixedViewport = false;
187    private boolean         mSupportMultipleWindows = false;
188    private boolean         mShrinksStandaloneImagesToFit = false;
189    private long            mMaximumDecodedImageSize = 0; // 0 means default
190    private boolean         mPrivateBrowsingEnabled = false;
191    private boolean         mSyntheticLinksEnabled = true;
192    // HTML5 API flags
193    private boolean         mAppCacheEnabled = false;
194    private boolean         mDatabaseEnabled = false;
195    private boolean         mDomStorageEnabled = false;
196    private boolean         mWorkersEnabled = false;  // only affects V8.
197    private boolean         mGeolocationEnabled = true;
198    private boolean         mXSSAuditorEnabled = false;
199    // HTML5 configuration parameters
200    private long            mAppCacheMaxSize = Long.MAX_VALUE;
201    private String          mAppCachePath = "";
202    private String          mDatabasePath = "";
203    // The WebCore DatabaseTracker only allows the database path to be set
204    // once. Keep track of when the path has been set.
205    private boolean         mDatabasePathHasBeenSet = false;
206    private String          mGeolocationDatabasePath = "";
207    // Don't need to synchronize the get/set methods as they
208    // are basic types, also none of these values are used in
209    // native WebCore code.
210    private ZoomDensity     mDefaultZoom = ZoomDensity.MEDIUM;
211    private RenderPriority  mRenderPriority = RenderPriority.NORMAL;
212    private int             mOverrideCacheMode = LOAD_DEFAULT;
213    private boolean         mSaveFormData = true;
214    private boolean         mAutoFillEnabled = false;
215    private boolean         mSavePassword = true;
216    private boolean         mLightTouchEnabled = false;
217    private boolean         mNeedInitialFocus = true;
218    private boolean         mNavDump = false;
219    private boolean         mSupportZoom = true;
220    private boolean         mBuiltInZoomControls = false;
221    private boolean         mDisplayZoomControls = true;
222    private boolean         mAllowFileAccess = true;
223    private boolean         mAllowContentAccess = true;
224    private boolean         mLoadWithOverviewMode = false;
225    private boolean         mEnableSmoothTransition = 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        // Detect tablet device for fixed viewport mode.
385        final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
386        final int landscapeWidth = Math.max(metrics.widthPixels, metrics.heightPixels);
387        final int minTabletWidth = context.getResources().getDimensionPixelSize(
388            com.android.internal.R.dimen.min_xlarge_screen_width);
389        mUseFixedViewport = (metrics.density == 1.0f && landscapeWidth >= minTabletWidth);
390
391        if (sLockForLocaleSettings == null) {
392            sLockForLocaleSettings = new Object();
393            sLocale = Locale.getDefault();
394        }
395        mAcceptLanguage = getCurrentAcceptLanguage();
396        mUserAgent = getCurrentUserAgent();
397        mUseDefaultUserAgent = true;
398
399        mBlockNetworkLoads = mContext.checkPermission(
400                "android.permission.INTERNET", android.os.Process.myPid(),
401                android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED;
402    }
403
404    private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";
405
406    /**
407     * Looks at sLocale and returns current AcceptLanguage String.
408     * @return Current AcceptLanguage String.
409     */
410    private String getCurrentAcceptLanguage() {
411        Locale locale;
412        synchronized(sLockForLocaleSettings) {
413            locale = sLocale;
414        }
415        StringBuilder buffer = new StringBuilder();
416        addLocaleToHttpAcceptLanguage(buffer, locale);
417
418        if (!Locale.US.equals(locale)) {
419            if (buffer.length() > 0) {
420                buffer.append(", ");
421            }
422            buffer.append(ACCEPT_LANG_FOR_US_LOCALE);
423        }
424
425        return buffer.toString();
426    }
427
428    /**
429     * Convert obsolete language codes, including Hebrew/Indonesian/Yiddish,
430     * to new standard.
431     */
432    private static String convertObsoleteLanguageCodeToNew(String langCode) {
433        if (langCode == null) {
434            return null;
435        }
436        if ("iw".equals(langCode)) {
437            // Hebrew
438            return "he";
439        } else if ("in".equals(langCode)) {
440            // Indonesian
441            return "id";
442        } else if ("ji".equals(langCode)) {
443            // Yiddish
444            return "yi";
445        }
446        return langCode;
447    }
448
449    private static void addLocaleToHttpAcceptLanguage(StringBuilder builder,
450                                                      Locale locale) {
451        String language = convertObsoleteLanguageCodeToNew(locale.getLanguage());
452        if (language != null) {
453            builder.append(language);
454            String country = locale.getCountry();
455            if (country != null) {
456                builder.append("-");
457                builder.append(country);
458            }
459        }
460    }
461
462    /**
463     * Looks at sLocale and mContext and returns current UserAgent String.
464     * @return Current UserAgent String.
465     */
466    private synchronized String getCurrentUserAgent() {
467        Locale locale;
468        synchronized(sLockForLocaleSettings) {
469            locale = sLocale;
470        }
471        StringBuffer buffer = new StringBuffer();
472        // Add version
473        final String version = Build.VERSION.RELEASE;
474        if (version.length() > 0) {
475            if (Character.isDigit(version.charAt(0))) {
476                // Release is a version, eg "3.1"
477                buffer.append(version);
478            } else {
479                // Release is a codename, eg "Honeycomb"
480                // In this case, use the previous release's version
481                buffer.append(PREVIOUS_VERSION);
482            }
483        } else {
484            // default to "1.0"
485            buffer.append("1.0");
486        }
487        buffer.append("; ");
488        final String language = locale.getLanguage();
489        if (language != null) {
490            buffer.append(convertObsoleteLanguageCodeToNew(language));
491            final String country = locale.getCountry();
492            if (country != null) {
493                buffer.append("-");
494                buffer.append(country.toLowerCase());
495            }
496        } else {
497            // default to "en"
498            buffer.append("en");
499        }
500        buffer.append(";");
501        // add the model for the release build
502        if ("REL".equals(Build.VERSION.CODENAME)) {
503            final String model = Build.MODEL;
504            if (model.length() > 0) {
505                buffer.append(" ");
506                buffer.append(model);
507            }
508        }
509        final String id = Build.ID;
510        if (id.length() > 0) {
511            buffer.append(" Build/");
512            buffer.append(id);
513        }
514        String mobile = mContext.getResources().getText(
515            com.android.internal.R.string.web_user_agent_target_content).toString();
516        final String base = mContext.getResources().getText(
517                com.android.internal.R.string.web_user_agent).toString();
518        return String.format(base, buffer, mobile);
519    }
520
521    /**
522     * Enables dumping the pages navigation cache to a text file.
523     * @deprecated This method is now obsolete.
524     */
525    @Deprecated
526    public void setNavDump(boolean enabled) {
527        mNavDump = enabled;
528    }
529
530    /**
531     * Returns true if dumping the navigation cache is enabled.
532     * @deprecated This method is now obsolete.
533     */
534    @Deprecated
535    public boolean getNavDump() {
536        return mNavDump;
537    }
538
539    /**
540     * If WebView only supports touch, a different navigation model will be
541     * applied. Otherwise, the navigation to support both touch and keyboard
542     * will be used.
543     * @hide
544    public void setSupportTouchOnly(boolean touchOnly) {
545        mSupportTounchOnly = touchOnly;
546    }
547     */
548
549    boolean supportTouchOnly() {
550        // for debug only, use mLightTouchEnabled for mSupportTounchOnly
551        return mLightTouchEnabled;
552    }
553
554    /**
555     * Set whether the WebView supports zoom
556     */
557    public void setSupportZoom(boolean support) {
558        mSupportZoom = support;
559        mWebView.updateMultiTouchSupport(mContext);
560    }
561
562    /**
563     * Returns whether the WebView supports zoom
564     */
565    public boolean supportZoom() {
566        return mSupportZoom;
567    }
568
569    /**
570     * Sets whether the zoom mechanism built into WebView is used.
571     */
572    public void setBuiltInZoomControls(boolean enabled) {
573        mBuiltInZoomControls = enabled;
574        mWebView.updateMultiTouchSupport(mContext);
575    }
576
577    /**
578     * Returns true if the zoom mechanism built into WebView is being used.
579     */
580    public boolean getBuiltInZoomControls() {
581        return mBuiltInZoomControls;
582    }
583
584    /**
585     * Sets whether the on screen zoom buttons are used.
586     * A combination of built in zoom controls enabled
587     * and on screen zoom controls disabled allows for pinch to zoom
588     * to work without the on screen controls
589     */
590    public void setDisplayZoomControls(boolean enabled) {
591        mDisplayZoomControls = enabled;
592        mWebView.updateMultiTouchSupport(mContext);
593    }
594
595    /**
596     * Returns true if the on screen zoom buttons are being used.
597     */
598    public boolean getDisplayZoomControls() {
599        return mDisplayZoomControls;
600    }
601
602    /**
603     * Enable or disable file access within WebView. File access is enabled by
604     * default.  Note that this enables or disables file system access only.
605     * Assets and resources are still accessible using file:///android_asset and
606     * file:///android_res.
607     */
608    public void setAllowFileAccess(boolean allow) {
609        mAllowFileAccess = allow;
610    }
611
612    /**
613     * Returns true if this WebView supports file access.
614     */
615    public boolean getAllowFileAccess() {
616        return mAllowFileAccess;
617    }
618
619    /**
620     * Enable or disable content url access within WebView.  Content url access
621     * allows WebView to load content from a content provider installed in the
622     * system.  The default is enabled.
623     */
624    public void setAllowContentAccess(boolean allow) {
625        mAllowContentAccess = allow;
626    }
627
628    /**
629     * Returns true if this WebView supports content url access.
630     */
631    public boolean getAllowContentAccess() {
632        return mAllowContentAccess;
633    }
634
635    /**
636     * Set whether the WebView loads a page with overview mode.
637     */
638    public void setLoadWithOverviewMode(boolean overview) {
639        mLoadWithOverviewMode = overview;
640    }
641
642    /**
643     * Returns true if this WebView loads page with overview mode
644     */
645    public boolean getLoadWithOverviewMode() {
646        return mLoadWithOverviewMode;
647    }
648
649    /**
650     * Set whether the WebView will enable smooth transition while panning or
651     * zooming. If it is true, WebView will choose a solution to maximize the
652     * performance. e.g. the WebView's content may not be updated during the
653     * transition. If it is false, WebView will keep its fidelity. The default
654     * value is false.
655     */
656    public void setEnableSmoothTransition(boolean enable) {
657        mEnableSmoothTransition = enable;
658    }
659
660    /**
661     * Returns true if the WebView enables smooth transition while panning or
662     * zooming.
663     */
664    public boolean enableSmoothTransition() {
665        return mEnableSmoothTransition;
666    }
667
668    /**
669     * Set whether the WebView uses its background for over scroll background.
670     * If true, it will use the WebView's background. If false, it will use an
671     * internal pattern. Default is true.
672     * @deprecated This method is now obsolete.
673     */
674    @Deprecated
675    public void setUseWebViewBackgroundForOverscrollBackground(boolean view) {
676        mUseWebViewBackgroundForOverscroll = view;
677    }
678
679    /**
680     * Returns true if this WebView uses WebView's background instead of
681     * internal pattern for over scroll background.
682     * @deprecated This method is now obsolete.
683     */
684    @Deprecated
685    public boolean getUseWebViewBackgroundForOverscrollBackground() {
686        return mUseWebViewBackgroundForOverscroll;
687    }
688
689    /**
690     * Store whether the WebView is saving form data.
691     */
692    public void setSaveFormData(boolean save) {
693        mSaveFormData = save;
694    }
695
696    /**
697     *  Return whether the WebView is saving form data and displaying prior
698     *  entries/autofill++.  Always false in private browsing mode.
699     */
700    public boolean getSaveFormData() {
701        return mSaveFormData && !mPrivateBrowsingEnabled;
702    }
703
704    /**
705     *  Store whether the WebView is saving password.
706     */
707    public void setSavePassword(boolean save) {
708        mSavePassword = save;
709    }
710
711    /**
712     *  Return whether the WebView is saving password.
713     */
714    public boolean getSavePassword() {
715        return mSavePassword;
716    }
717
718    /**
719     * Set the text size of the page.
720     * @param t A TextSize value for increasing or decreasing the text.
721     * @see WebSettings.TextSize
722     */
723    public synchronized void setTextSize(TextSize t) {
724        if (WebView.mLogEvent && mTextSize != t ) {
725            EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE,
726                    mTextSize.value, t.value);
727        }
728        mTextSize = t;
729        postSync();
730    }
731
732    /**
733     * Get the text size of the page.
734     * @return A TextSize enum value describing the text size.
735     * @see WebSettings.TextSize
736     */
737    public synchronized TextSize getTextSize() {
738        return mTextSize;
739    }
740
741    /**
742     * Set the default zoom density of the page. This should be called from UI
743     * thread.
744     * @param zoom A ZoomDensity value
745     * @see WebSettings.ZoomDensity
746     */
747    public void setDefaultZoom(ZoomDensity zoom) {
748        if (mDefaultZoom != zoom) {
749            mDefaultZoom = zoom;
750            mWebView.updateDefaultZoomDensity(zoom.value);
751        }
752    }
753
754    /**
755     * Get the default zoom density of the page. This should be called from UI
756     * thread.
757     * @return A ZoomDensity value
758     * @see WebSettings.ZoomDensity
759     */
760    public ZoomDensity getDefaultZoom() {
761        return mDefaultZoom;
762    }
763
764    /**
765     * Enables using light touches to make a selection and activate mouseovers.
766     */
767    public void setLightTouchEnabled(boolean enabled) {
768        mLightTouchEnabled = enabled;
769    }
770
771    /**
772     * Returns true if light touches are enabled.
773     */
774    public boolean getLightTouchEnabled() {
775        return mLightTouchEnabled;
776    }
777
778    /**
779     * @deprecated This setting controlled a rendering optimization
780     * that is no longer present. Setting it now has no effect.
781     */
782    @Deprecated
783    public synchronized void setUseDoubleTree(boolean use) {
784        return;
785    }
786
787    /**
788     * @deprecated This setting controlled a rendering optimization
789     * that is no longer present. Setting it now has no effect.
790     */
791    @Deprecated
792    public synchronized boolean getUseDoubleTree() {
793        return false;
794    }
795
796    /**
797     * Tell the WebView about user-agent string.
798     * @param ua 0 if the WebView should use an Android user-agent string,
799     *           1 if the WebView should use a desktop user-agent string.
800     *
801     * @deprecated Please use setUserAgentString instead.
802     */
803    @Deprecated
804    public synchronized void setUserAgent(int ua) {
805        String uaString = null;
806        if (ua == 1) {
807            if (DESKTOP_USERAGENT.equals(mUserAgent)) {
808                return; // do nothing
809            } else {
810                uaString = DESKTOP_USERAGENT;
811            }
812        } else if (ua == 2) {
813            if (IPHONE_USERAGENT.equals(mUserAgent)) {
814                return; // do nothing
815            } else {
816                uaString = IPHONE_USERAGENT;
817            }
818        } else if (ua != 0) {
819            return; // do nothing
820        }
821        setUserAgentString(uaString);
822    }
823
824    /**
825     * Return user-agent as int
826     * @return int  0 if the WebView is using an Android user-agent string.
827     *              1 if the WebView is using a desktop user-agent string.
828     *             -1 if the WebView is using user defined user-agent string.
829     *
830     * @deprecated Please use getUserAgentString instead.
831     */
832    @Deprecated
833    public synchronized int getUserAgent() {
834        if (DESKTOP_USERAGENT.equals(mUserAgent)) {
835            return 1;
836        } else if (IPHONE_USERAGENT.equals(mUserAgent)) {
837            return 2;
838        } else if (mUseDefaultUserAgent) {
839            return 0;
840        }
841        return -1;
842    }
843
844    /**
845     * Tell the WebView to use the wide viewport
846     */
847    public synchronized void setUseWideViewPort(boolean use) {
848        if (mUseWideViewport != use) {
849            mUseWideViewport = use;
850            postSync();
851        }
852    }
853
854    /**
855     * @return True if the WebView is using a wide viewport
856     */
857    public synchronized boolean getUseWideViewPort() {
858        return mUseWideViewport;
859    }
860
861    /**
862     * Tell the WebView whether it supports multiple windows. TRUE means
863     *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
864     *         boolean, Message)} is implemented by the host application.
865     */
866    public synchronized void setSupportMultipleWindows(boolean support) {
867        if (mSupportMultipleWindows != support) {
868            mSupportMultipleWindows = support;
869            postSync();
870        }
871    }
872
873    /**
874     * @return True if the WebView is supporting multiple windows. This means
875     *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
876     *         boolean, Message)} is implemented by the host application.
877     */
878    public synchronized boolean supportMultipleWindows() {
879        return mSupportMultipleWindows;
880    }
881
882    /**
883     * Set the underlying layout algorithm. This will cause a relayout of the
884     * WebView.
885     * @param l A LayoutAlgorithm enum specifying the algorithm to use.
886     * @see WebSettings.LayoutAlgorithm
887     * @deprecated This method is now obsolete.
888     */
889    @Deprecated
890    public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
891        // XXX: This will only be affective if libwebcore was built with
892        // ANDROID_LAYOUT defined.
893        if (mLayoutAlgorithm != l) {
894            mLayoutAlgorithm = l;
895            postSync();
896        }
897    }
898
899    /**
900     * Return the current layout algorithm. The default is NARROW_COLUMNS.
901     * @return LayoutAlgorithm enum value describing the layout algorithm
902     *         being used.
903     * @see WebSettings.LayoutAlgorithm
904     * @deprecated This method is now obsolete.
905     */
906    @Deprecated
907    public synchronized LayoutAlgorithm getLayoutAlgorithm() {
908        return mLayoutAlgorithm;
909    }
910
911    /**
912     * Set the standard font family name.
913     * @param font A font family name.
914     */
915    public synchronized void setStandardFontFamily(String font) {
916        if (font != null && !font.equals(mStandardFontFamily)) {
917            mStandardFontFamily = font;
918            postSync();
919        }
920    }
921
922    /**
923     * Get the standard font family name. The default is "sans-serif".
924     * @return The standard font family name as a string.
925     */
926    public synchronized String getStandardFontFamily() {
927        return mStandardFontFamily;
928    }
929
930    /**
931     * Set the fixed font family name.
932     * @param font A font family name.
933     */
934    public synchronized void setFixedFontFamily(String font) {
935        if (font != null && !font.equals(mFixedFontFamily)) {
936            mFixedFontFamily = font;
937            postSync();
938        }
939    }
940
941    /**
942     * Get the fixed font family name. The default is "monospace".
943     * @return The fixed font family name as a string.
944     */
945    public synchronized String getFixedFontFamily() {
946        return mFixedFontFamily;
947    }
948
949    /**
950     * Set the sans-serif font family name.
951     * @param font A font family name.
952     */
953    public synchronized void setSansSerifFontFamily(String font) {
954        if (font != null && !font.equals(mSansSerifFontFamily)) {
955            mSansSerifFontFamily = font;
956            postSync();
957        }
958    }
959
960    /**
961     * Get the sans-serif font family name.
962     * @return The sans-serif font family name as a string.
963     */
964    public synchronized String getSansSerifFontFamily() {
965        return mSansSerifFontFamily;
966    }
967
968    /**
969     * Set the serif font family name. The default is "sans-serif".
970     * @param font A font family name.
971     */
972    public synchronized void setSerifFontFamily(String font) {
973        if (font != null && !font.equals(mSerifFontFamily)) {
974            mSerifFontFamily = font;
975            postSync();
976        }
977    }
978
979    /**
980     * Get the serif font family name. The default is "serif".
981     * @return The serif font family name as a string.
982     */
983    public synchronized String getSerifFontFamily() {
984        return mSerifFontFamily;
985    }
986
987    /**
988     * Set the cursive font family name.
989     * @param font A font family name.
990     */
991    public synchronized void setCursiveFontFamily(String font) {
992        if (font != null && !font.equals(mCursiveFontFamily)) {
993            mCursiveFontFamily = font;
994            postSync();
995        }
996    }
997
998    /**
999     * Get the cursive font family name. The default is "cursive".
1000     * @return The cursive font family name as a string.
1001     */
1002    public synchronized String getCursiveFontFamily() {
1003        return mCursiveFontFamily;
1004    }
1005
1006    /**
1007     * Set the fantasy font family name.
1008     * @param font A font family name.
1009     */
1010    public synchronized void setFantasyFontFamily(String font) {
1011        if (font != null && !font.equals(mFantasyFontFamily)) {
1012            mFantasyFontFamily = font;
1013            postSync();
1014        }
1015    }
1016
1017    /**
1018     * Get the fantasy font family name. The default is "fantasy".
1019     * @return The fantasy font family name as a string.
1020     */
1021    public synchronized String getFantasyFontFamily() {
1022        return mFantasyFontFamily;
1023    }
1024
1025    /**
1026     * Set the minimum font size.
1027     * @param size A non-negative integer between 1 and 72.
1028     * Any number outside the specified range will be pinned.
1029     */
1030    public synchronized void setMinimumFontSize(int size) {
1031        size = pin(size);
1032        if (mMinimumFontSize != size) {
1033            mMinimumFontSize = size;
1034            postSync();
1035        }
1036    }
1037
1038    /**
1039     * Get the minimum font size. The default is 8.
1040     * @return A non-negative integer between 1 and 72.
1041     */
1042    public synchronized int getMinimumFontSize() {
1043        return mMinimumFontSize;
1044    }
1045
1046    /**
1047     * Set the minimum logical font size.
1048     * @param size A non-negative integer between 1 and 72.
1049     * Any number outside the specified range will be pinned.
1050     */
1051    public synchronized void setMinimumLogicalFontSize(int size) {
1052        size = pin(size);
1053        if (mMinimumLogicalFontSize != size) {
1054            mMinimumLogicalFontSize = size;
1055            postSync();
1056        }
1057    }
1058
1059    /**
1060     * Get the minimum logical font size. The default is 8.
1061     * @return A non-negative integer between 1 and 72.
1062     */
1063    public synchronized int getMinimumLogicalFontSize() {
1064        return mMinimumLogicalFontSize;
1065    }
1066
1067    /**
1068     * Set the default font size.
1069     * @param size A non-negative integer between 1 and 72.
1070     * Any number outside the specified range will be pinned.
1071     */
1072    public synchronized void setDefaultFontSize(int size) {
1073        size = pin(size);
1074        if (mDefaultFontSize != size) {
1075            mDefaultFontSize = size;
1076            postSync();
1077        }
1078    }
1079
1080    /**
1081     * Get the default font size. The default is 16.
1082     * @return A non-negative integer between 1 and 72.
1083     */
1084    public synchronized int getDefaultFontSize() {
1085        return mDefaultFontSize;
1086    }
1087
1088    /**
1089     * Set the default fixed font size.
1090     * @param size A non-negative integer between 1 and 72.
1091     * Any number outside the specified range will be pinned.
1092     */
1093    public synchronized void setDefaultFixedFontSize(int size) {
1094        size = pin(size);
1095        if (mDefaultFixedFontSize != size) {
1096            mDefaultFixedFontSize = size;
1097            postSync();
1098        }
1099    }
1100
1101    /**
1102     * Get the default fixed font size. The default is 16.
1103     * @return A non-negative integer between 1 and 72.
1104     */
1105    public synchronized int getDefaultFixedFontSize() {
1106        return mDefaultFixedFontSize;
1107    }
1108
1109    /**
1110     * Set the number of pages cached by the WebKit for the history navigation.
1111     * @param size A non-negative integer between 0 (no cache) and 20 (max).
1112     * @hide
1113     */
1114    public synchronized void setPageCacheCapacity(int size) {
1115        if (size < 0) size = 0;
1116        if (size > 20) size = 20;
1117        if (mPageCacheCapacity != size) {
1118            mPageCacheCapacity = size;
1119            postSync();
1120        }
1121    }
1122
1123    /**
1124     * Tell the WebView to load image resources automatically.
1125     * @param flag True if the WebView should load images automatically.
1126     */
1127    public synchronized void setLoadsImagesAutomatically(boolean flag) {
1128        if (mLoadsImagesAutomatically != flag) {
1129            mLoadsImagesAutomatically = flag;
1130            postSync();
1131        }
1132    }
1133
1134    /**
1135     * Return true if the WebView will load image resources automatically.
1136     * The default is true.
1137     * @return True if the WebView loads images automatically.
1138     */
1139    public synchronized boolean getLoadsImagesAutomatically() {
1140        return mLoadsImagesAutomatically;
1141    }
1142
1143    /**
1144     * Tell the WebView to block network images. This is only checked when
1145     * {@link #getLoadsImagesAutomatically} is true. If you set the value to
1146     * false, images will automatically be loaded. Use this api to reduce
1147     * bandwidth only. Use {@link #setBlockNetworkLoads} if possible.
1148     * @param flag True if the WebView should block network images.
1149     * @see #setBlockNetworkLoads
1150     */
1151    public synchronized void setBlockNetworkImage(boolean flag) {
1152        if (mBlockNetworkImage != flag) {
1153            mBlockNetworkImage = flag;
1154            postSync();
1155        }
1156    }
1157
1158    /**
1159     * Return true if the WebView will block network images. The default is
1160     * false.
1161     * @return True if the WebView blocks network images.
1162     */
1163    public synchronized boolean getBlockNetworkImage() {
1164        return mBlockNetworkImage;
1165    }
1166
1167    /**
1168     * Tell the WebView to block all network load requests. If you set the
1169     * value to false, you must call {@link android.webkit.WebView#reload} to
1170     * fetch remote resources. This flag supercedes the value passed to
1171     * {@link #setBlockNetworkImage}.
1172     * @param flag True if the WebView should block all network loads.
1173     * @see android.webkit.WebView#reload
1174     */
1175    public synchronized void setBlockNetworkLoads(boolean flag) {
1176        if (mBlockNetworkLoads != flag) {
1177            mBlockNetworkLoads = flag;
1178            verifyNetworkAccess();
1179            postSync();
1180        }
1181    }
1182
1183    /**
1184     * Return true if the WebView will block all network loads. The default is
1185     * false.
1186     * @return True if the WebView blocks all network loads.
1187     */
1188    public synchronized boolean getBlockNetworkLoads() {
1189        return mBlockNetworkLoads;
1190    }
1191
1192
1193    private void verifyNetworkAccess() {
1194        if (!mBlockNetworkLoads) {
1195            if (mContext.checkPermission("android.permission.INTERNET",
1196                    android.os.Process.myPid(), android.os.Process.myUid()) !=
1197                        PackageManager.PERMISSION_GRANTED) {
1198                throw new SecurityException
1199                        ("Permission denied - " +
1200                                "application missing INTERNET permission");
1201            }
1202        }
1203    }
1204
1205    /**
1206     * Tell the WebView to enable javascript execution.
1207     * @param flag True if the WebView should execute javascript.
1208     */
1209    public synchronized void setJavaScriptEnabled(boolean flag) {
1210        if (mJavaScriptEnabled != flag) {
1211            mJavaScriptEnabled = flag;
1212            postSync();
1213        }
1214    }
1215
1216    /**
1217     * Tell the WebView to show the visual indicator
1218     * @param flag True if the WebView should show the visual indicator
1219     * @hide
1220     */
1221    public synchronized void setShowVisualIndicator(boolean flag) {
1222        if (mShowVisualIndicator != flag) {
1223            mShowVisualIndicator = flag;
1224            postSync();
1225        }
1226    }
1227
1228    /**
1229     * @return True if the WebView is showing the visual indicator
1230     * @hide
1231     */
1232    public synchronized boolean getShowVisualIndicator() {
1233        return mShowVisualIndicator;
1234    }
1235
1236    /**
1237     * Tell the WebView to enable plugins.
1238     * @param flag True if the WebView should load plugins.
1239     * @deprecated This method has been deprecated in favor of
1240     *             {@link #setPluginState}
1241     */
1242    @Deprecated
1243    public synchronized void setPluginsEnabled(boolean flag) {
1244        setPluginState(flag ? PluginState.ON : PluginState.OFF);
1245    }
1246
1247    /**
1248     * Tell the WebView to enable, disable, or have plugins on demand. On
1249     * demand mode means that if a plugin exists that can handle the embedded
1250     * content, a placeholder icon will be shown instead of the plugin. When
1251     * the placeholder is clicked, the plugin will be enabled.
1252     * @param state One of the PluginState values.
1253     */
1254    public synchronized void setPluginState(PluginState state) {
1255        if (mPluginState != state) {
1256            mPluginState = state;
1257            postSync();
1258        }
1259    }
1260
1261    /**
1262     * Set a custom path to plugins used by the WebView. This method is
1263     * obsolete since each plugin is now loaded from its own package.
1264     * @param pluginsPath String path to the directory containing plugins.
1265     * @deprecated This method is no longer used as plugins are loaded from
1266     * their own APK via the system's package manager.
1267     */
1268    @Deprecated
1269    public synchronized void setPluginsPath(String pluginsPath) {
1270    }
1271
1272    /**
1273     * Set the path to where database storage API databases should be saved.
1274     * Nota that the WebCore Database Tracker only allows the path to be set once.
1275     * This will update WebCore when the Sync runs in the C++ side.
1276     * @param databasePath String path to the directory where databases should
1277     *     be saved. May be the empty string but should never be null.
1278     */
1279    public synchronized void setDatabasePath(String databasePath) {
1280        if (databasePath != null && !mDatabasePathHasBeenSet) {
1281            mDatabasePath = databasePath;
1282            mDatabasePathHasBeenSet = true;
1283            postSync();
1284        }
1285    }
1286
1287    /**
1288     * Set the path where the Geolocation permissions database should be saved.
1289     * This will update WebCore when the Sync runs in the C++ side.
1290     * @param databasePath String path to the directory where the Geolocation
1291     *     permissions database should be saved. May be the empty string but
1292     *     should never be null.
1293     */
1294    public synchronized void setGeolocationDatabasePath(String databasePath) {
1295        if (databasePath != null
1296                && !databasePath.equals(mGeolocationDatabasePath)) {
1297            mGeolocationDatabasePath = databasePath;
1298            postSync();
1299        }
1300    }
1301
1302    /**
1303     * Tell the WebView to enable Application Caches API.
1304     * @param flag True if the WebView should enable Application Caches.
1305     */
1306    public synchronized void setAppCacheEnabled(boolean flag) {
1307        if (mAppCacheEnabled != flag) {
1308            mAppCacheEnabled = flag;
1309            postSync();
1310        }
1311    }
1312
1313    /**
1314     * Set a custom path to the Application Caches files. The client
1315     * must ensure it exists before this call.
1316     * @param appCachePath String path to the directory containing Application
1317     * Caches files. The appCache path can be the empty string but should not
1318     * be null. Passing null for this parameter will result in a no-op.
1319     */
1320    public synchronized void setAppCachePath(String appCachePath) {
1321        if (appCachePath != null && !appCachePath.equals(mAppCachePath)) {
1322            mAppCachePath = appCachePath;
1323            postSync();
1324        }
1325    }
1326
1327    /**
1328     * Set the maximum size for the Application Caches content.
1329     * @param appCacheMaxSize the maximum size in bytes.
1330     */
1331    public synchronized void setAppCacheMaxSize(long appCacheMaxSize) {
1332        if (appCacheMaxSize != mAppCacheMaxSize) {
1333            mAppCacheMaxSize = appCacheMaxSize;
1334            postSync();
1335        }
1336    }
1337
1338    /**
1339     * Set whether the database storage API is enabled.
1340     * @param flag boolean True if the WebView should use the database storage
1341     *     API.
1342     */
1343    public synchronized void setDatabaseEnabled(boolean flag) {
1344       if (mDatabaseEnabled != flag) {
1345           mDatabaseEnabled = flag;
1346           postSync();
1347       }
1348    }
1349
1350    /**
1351     * Set whether the DOM storage API is enabled.
1352     * @param flag boolean True if the WebView should use the DOM storage
1353     *     API.
1354     */
1355    public synchronized void setDomStorageEnabled(boolean flag) {
1356       if (mDomStorageEnabled != flag) {
1357           mDomStorageEnabled = flag;
1358           postSync();
1359       }
1360    }
1361
1362    /**
1363     * Returns true if the DOM Storage API's are enabled.
1364     * @return True if the DOM Storage API's are enabled.
1365     */
1366    public synchronized boolean getDomStorageEnabled() {
1367       return mDomStorageEnabled;
1368    }
1369
1370    /**
1371     * Return the path to where database storage API databases are saved for
1372     * the current WebView.
1373     * @return the String path to the database storage API databases.
1374     */
1375    public synchronized String getDatabasePath() {
1376        return mDatabasePath;
1377    }
1378
1379    /**
1380     * Returns true if database storage API is enabled.
1381     * @return True if the database storage API is enabled.
1382     */
1383    public synchronized boolean getDatabaseEnabled() {
1384        return mDatabaseEnabled;
1385    }
1386
1387    /**
1388     * Tell the WebView to enable WebWorkers API.
1389     * @param flag True if the WebView should enable WebWorkers.
1390     * Note that this flag only affects V8. JSC does not have
1391     * an equivalent setting.
1392     * @hide pending api council approval
1393     */
1394    public synchronized void setWorkersEnabled(boolean flag) {
1395        if (mWorkersEnabled != flag) {
1396            mWorkersEnabled = flag;
1397            postSync();
1398        }
1399    }
1400
1401    /**
1402     * Sets whether Geolocation is enabled.
1403     * @param flag Whether Geolocation should be enabled.
1404     */
1405    public synchronized void setGeolocationEnabled(boolean flag) {
1406        if (mGeolocationEnabled != flag) {
1407            mGeolocationEnabled = flag;
1408            postSync();
1409        }
1410    }
1411
1412    /**
1413     * Sets whether XSS Auditor is enabled.
1414     * @param flag Whether XSS Auditor should be enabled.
1415     * @hide Only used by LayoutTestController.
1416     */
1417    public synchronized void setXSSAuditorEnabled(boolean flag) {
1418        if (mXSSAuditorEnabled != flag) {
1419            mXSSAuditorEnabled = flag;
1420            postSync();
1421        }
1422    }
1423
1424    /**
1425     * Return true if javascript is enabled. <b>Note: The default is false.</b>
1426     * @return True if javascript is enabled.
1427     */
1428    public synchronized boolean getJavaScriptEnabled() {
1429        return mJavaScriptEnabled;
1430    }
1431
1432    /**
1433     * Return true if plugins are enabled.
1434     * @return True if plugins are enabled.
1435     * @deprecated This method has been replaced by {@link #getPluginState}
1436     */
1437    @Deprecated
1438    public synchronized boolean getPluginsEnabled() {
1439        return mPluginState == PluginState.ON;
1440    }
1441
1442    /**
1443     * Return the current plugin state.
1444     * @return A value corresponding to the enum PluginState.
1445     */
1446    public synchronized PluginState getPluginState() {
1447        return mPluginState;
1448    }
1449
1450    /**
1451     * Returns the directory that contains the plugin libraries. This method is
1452     * obsolete since each plugin is now loaded from its own package.
1453     * @return An empty string.
1454     * @deprecated This method is no longer used as plugins are loaded from
1455     * their own APK via the system's package manager.
1456     */
1457    @Deprecated
1458    public synchronized String getPluginsPath() {
1459        return "";
1460    }
1461
1462    /**
1463     * Tell javascript to open windows automatically. This applies to the
1464     * javascript function window.open().
1465     * @param flag True if javascript can open windows automatically.
1466     */
1467    public synchronized void setJavaScriptCanOpenWindowsAutomatically(
1468            boolean flag) {
1469        if (mJavaScriptCanOpenWindowsAutomatically != flag) {
1470            mJavaScriptCanOpenWindowsAutomatically = flag;
1471            postSync();
1472        }
1473    }
1474
1475    /**
1476     * Return true if javascript can open windows automatically. The default
1477     * is false.
1478     * @return True if javascript can open windows automatically during
1479     *         window.open().
1480     */
1481    public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() {
1482        return mJavaScriptCanOpenWindowsAutomatically;
1483    }
1484
1485    /**
1486     * Set the default text encoding name to use when decoding html pages.
1487     * @param encoding The text encoding name.
1488     */
1489    public synchronized void setDefaultTextEncodingName(String encoding) {
1490        if (encoding != null && !encoding.equals(mDefaultTextEncoding)) {
1491            mDefaultTextEncoding = encoding;
1492            postSync();
1493        }
1494    }
1495
1496    /**
1497     * Get the default text encoding name. The default is "Latin-1".
1498     * @return The default text encoding name as a string.
1499     */
1500    public synchronized String getDefaultTextEncodingName() {
1501        return mDefaultTextEncoding;
1502    }
1503
1504    /**
1505     * Set the WebView's user-agent string. If the string "ua" is null or empty,
1506     * it will use the system default user-agent string.
1507     */
1508    public synchronized void setUserAgentString(String ua) {
1509        if (ua == null || ua.length() == 0) {
1510            synchronized(sLockForLocaleSettings) {
1511                Locale currentLocale = Locale.getDefault();
1512                if (!sLocale.equals(currentLocale)) {
1513                    sLocale = currentLocale;
1514                    mAcceptLanguage = getCurrentAcceptLanguage();
1515                }
1516            }
1517            ua = getCurrentUserAgent();
1518            mUseDefaultUserAgent = true;
1519        } else  {
1520            mUseDefaultUserAgent = false;
1521        }
1522
1523        if (!ua.equals(mUserAgent)) {
1524            mUserAgent = ua;
1525            postSync();
1526        }
1527    }
1528
1529    /**
1530     * Return the WebView's user-agent string.
1531     */
1532    public synchronized String getUserAgentString() {
1533        if (DESKTOP_USERAGENT.equals(mUserAgent) ||
1534                IPHONE_USERAGENT.equals(mUserAgent) ||
1535                !mUseDefaultUserAgent) {
1536            return mUserAgent;
1537        }
1538
1539        boolean doPostSync = false;
1540        synchronized(sLockForLocaleSettings) {
1541            Locale currentLocale = Locale.getDefault();
1542            if (!sLocale.equals(currentLocale)) {
1543                sLocale = currentLocale;
1544                mUserAgent = getCurrentUserAgent();
1545                mAcceptLanguage = getCurrentAcceptLanguage();
1546                doPostSync = true;
1547            }
1548        }
1549        if (doPostSync) {
1550            postSync();
1551        }
1552        return mUserAgent;
1553    }
1554
1555    /* package api to grab the Accept Language string. */
1556    /*package*/ synchronized String getAcceptLanguage() {
1557        synchronized(sLockForLocaleSettings) {
1558            Locale currentLocale = Locale.getDefault();
1559            if (!sLocale.equals(currentLocale)) {
1560                sLocale = currentLocale;
1561                mAcceptLanguage = getCurrentAcceptLanguage();
1562            }
1563        }
1564        return mAcceptLanguage;
1565    }
1566
1567    /* package */ boolean isNarrowColumnLayout() {
1568        return getLayoutAlgorithm() == LayoutAlgorithm.NARROW_COLUMNS;
1569    }
1570
1571    /**
1572     * Tell the WebView whether it needs to set a node to have focus when
1573     * {@link WebView#requestFocus(int, android.graphics.Rect)} is called.
1574     *
1575     * @param flag
1576     */
1577    public void setNeedInitialFocus(boolean flag) {
1578        if (mNeedInitialFocus != flag) {
1579            mNeedInitialFocus = flag;
1580        }
1581    }
1582
1583    /* Package api to get the choice whether it needs to set initial focus. */
1584    /* package */ boolean getNeedInitialFocus() {
1585        return mNeedInitialFocus;
1586    }
1587
1588    /**
1589     * Set the priority of the Render thread. Unlike the other settings, this
1590     * one only needs to be called once per process. The default is NORMAL.
1591     *
1592     * @param priority RenderPriority, can be normal, high or low.
1593     */
1594    public synchronized void setRenderPriority(RenderPriority priority) {
1595        if (mRenderPriority != priority) {
1596            mRenderPriority = priority;
1597            mEventHandler.sendMessage(Message.obtain(null,
1598                    EventHandler.PRIORITY));
1599        }
1600    }
1601
1602    /**
1603     * Override the way the cache is used. The way the cache is used is based
1604     * on the navigation option. For a normal page load, the cache is checked
1605     * and content is re-validated as needed. When navigating back, content is
1606     * not revalidated, instead the content is just pulled from the cache.
1607     * This function allows the client to override this behavior.
1608     * @param mode One of the LOAD_ values.
1609     */
1610    public void setCacheMode(int mode) {
1611        if (mode != mOverrideCacheMode) {
1612            mOverrideCacheMode = mode;
1613            postSync();
1614        }
1615    }
1616
1617    /**
1618     * Return the current setting for overriding the cache mode. For a full
1619     * description, see the {@link #setCacheMode(int)} function.
1620     */
1621    public int getCacheMode() {
1622        return mOverrideCacheMode;
1623    }
1624
1625    /**
1626     * If set, webkit alternately shrinks and expands images viewed outside
1627     * of an HTML page to fit the screen. This conflicts with attempts by
1628     * the UI to zoom in and out of an image, so it is set false by default.
1629     * @param shrink Set true to let webkit shrink the standalone image to fit.
1630     * {@hide}
1631     */
1632    public void setShrinksStandaloneImagesToFit(boolean shrink) {
1633        if (mShrinksStandaloneImagesToFit != shrink) {
1634            mShrinksStandaloneImagesToFit = shrink;
1635            postSync();
1636        }
1637     }
1638
1639    /**
1640     * Specify the maximum decoded image size. The default is
1641     * 2 megs for small memory devices and 8 megs for large memory devices.
1642     * @param size The maximum decoded size, or zero to set to the default.
1643     * @hide pending api council approval
1644     */
1645    public void setMaximumDecodedImageSize(long size) {
1646        if (mMaximumDecodedImageSize != size) {
1647            mMaximumDecodedImageSize = size;
1648            postSync();
1649        }
1650    }
1651
1652    /**
1653     * Returns whether to use fixed viewport.  Fixed viewport should operate only
1654     * when wide viewport is on.
1655     */
1656    /* package */ boolean getUseFixedViewport() {
1657        return getUseWideViewPort() && mUseFixedViewport;
1658    }
1659
1660    /**
1661     * Returns whether private browsing is enabled.
1662     */
1663    /* package */ boolean isPrivateBrowsingEnabled() {
1664        return mPrivateBrowsingEnabled;
1665    }
1666
1667    /**
1668     * Sets whether private browsing is enabled.
1669     * @param flag Whether private browsing should be enabled.
1670     */
1671    /* package */ synchronized void setPrivateBrowsingEnabled(boolean flag) {
1672        if (mPrivateBrowsingEnabled != flag) {
1673            mPrivateBrowsingEnabled = flag;
1674
1675            // AutoFill is dependant on private browsing being enabled so
1676            // reset it to take account of the new value of mPrivateBrowsingEnabled.
1677            setAutoFillEnabled(mAutoFillEnabled);
1678
1679            postSync();
1680        }
1681    }
1682
1683    synchronized void setSyntheticLinksEnabled(boolean flag) {
1684        if (mSyntheticLinksEnabled != flag) {
1685            mSyntheticLinksEnabled = flag;
1686            postSync();
1687        }
1688    }
1689
1690    /**
1691     * @hide
1692     */
1693    public synchronized void setAutoFillEnabled(boolean enabled) {
1694        // AutoFill is always disabled in private browsing mode.
1695        boolean autoFillEnabled = enabled && !mPrivateBrowsingEnabled;
1696        if (mAutoFillEnabled != autoFillEnabled) {
1697            mAutoFillEnabled = autoFillEnabled;
1698            postSync();
1699        }
1700    }
1701
1702    /**
1703     * @hide
1704     */
1705    public synchronized boolean getAutoFillEnabled() {
1706        return mAutoFillEnabled;
1707    }
1708
1709    /**
1710     * @hide
1711     */
1712    public synchronized void setAutoFillProfile(AutoFillProfile profile) {
1713        if (mAutoFillProfile != profile) {
1714            mAutoFillProfile = profile;
1715            postSync();
1716        }
1717    }
1718
1719    /**
1720     * @hide
1721     */
1722    public synchronized AutoFillProfile getAutoFillProfile() {
1723        return mAutoFillProfile;
1724    }
1725
1726    int getDoubleTapToastCount() {
1727        return mDoubleTapToastCount;
1728    }
1729
1730    void setDoubleTapToastCount(int count) {
1731        if (mDoubleTapToastCount != count) {
1732            mDoubleTapToastCount = count;
1733            // write the settings in the non-UI thread
1734            mEventHandler.sendMessage(Message.obtain(null,
1735                    EventHandler.SET_DOUBLE_TAP_TOAST_COUNT));
1736        }
1737    }
1738
1739    /**
1740     * Transfer messages from the queue to the new WebCoreThread. Called from
1741     * WebCore thread.
1742     */
1743    /*package*/
1744    synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
1745        mBrowserFrame = frame;
1746        if (DebugFlags.WEB_SETTINGS) {
1747            junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
1748        }
1749
1750        SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE,
1751                Context.MODE_PRIVATE);
1752        if (mDoubleTapToastCount > 0) {
1753            mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
1754                    mDoubleTapToastCount);
1755        }
1756        nativeSync(frame.mNativeFrame);
1757        mSyncPending = false;
1758        mEventHandler.createHandler();
1759    }
1760
1761    /**
1762     * Let the Settings object know that our owner is being destroyed.
1763     */
1764    /*package*/
1765    synchronized void onDestroyed() {
1766    }
1767
1768    private int pin(int size) {
1769        // FIXME: 72 is just an arbitrary max text size value.
1770        if (size < 1) {
1771            return 1;
1772        } else if (size > 72) {
1773            return 72;
1774        }
1775        return size;
1776    }
1777
1778    /* Post a SYNC message to handle syncing the native settings. */
1779    private synchronized void postSync() {
1780        // Only post if a sync is not pending
1781        if (!mSyncPending) {
1782            mSyncPending = mEventHandler.sendMessage(
1783                    Message.obtain(null, EventHandler.SYNC));
1784        }
1785    }
1786
1787    // Synchronize the native and java settings.
1788    private native void nativeSync(int nativeFrame);
1789}
1790