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