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