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