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