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