WebSettings.java revision c27a9acb3b7ec4d1845b623cc167e0b62b1d0585
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.pm.PackageManager;
21import android.os.Build;
22import android.os.Handler;
23import android.os.Message;
24import android.provider.Checkin;
25import java.lang.SecurityException;
26import java.util.Locale;
27
28/**
29 * Manages settings state for a WebView. When a WebView is first created, it
30 * obtains a set of default settings. These default settings will be returned
31 * from any getter call. A WebSettings object obtained from
32 * WebView.getSettings() is tied to the life of the WebView. If a WebView has
33 * been destroyed, any method call on WebSettings will throw an
34 * IllegalStateException.
35 */
36public class WebSettings {
37    /**
38     * Enum for controlling the layout of html.
39     * NORMAL means no rendering changes.
40     * SINGLE_COLUMN moves all content into one column that is the width of the
41     * view.
42     * NARROW_COLUMNS makes all columns no wider than the screen if possible.
43     */
44    // XXX: These must match LayoutAlgorithm in Settings.h in WebCore.
45    public enum LayoutAlgorithm {
46        NORMAL,
47        SINGLE_COLUMN,
48        NARROW_COLUMNS
49    }
50
51    /**
52     * Enum for specifying the text size.
53     * SMALLEST is 50%
54     * SMALLER is 75%
55     * NORMAL is 100%
56     * LARGER is 150%
57     * LARGEST is 200%
58     */
59    public enum TextSize {
60        SMALLEST(50),
61        SMALLER(75),
62        NORMAL(100),
63        LARGER(150),
64        LARGEST(200);
65        TextSize(int size) {
66            value = size;
67        }
68        int value;
69    }
70
71    /**
72     * Enum for specifying the WebView's desired density.
73     * FAR makes 100% looking like in 240dpi
74     * MEDIUM makes 100% looking like in 160dpi
75     * CLOSE makes 100% looking like in 120dpi
76     * @hide Pending API council approval
77     */
78    public enum ZoomDensity {
79        FAR(150),      // 240dpi
80        MEDIUM(100),    // 160dpi
81        CLOSE(75);     // 120dpi
82        ZoomDensity(int size) {
83            value = size;
84        }
85        int value;
86    }
87
88    /**
89     * Default cache usage pattern  Use with {@link #setCacheMode}.
90     */
91    public static final int LOAD_DEFAULT = -1;
92
93    /**
94     * Normal cache usage pattern  Use with {@link #setCacheMode}.
95     */
96    public static final int LOAD_NORMAL = 0;
97
98    /**
99     * Use cache if content is there, even if expired (eg, history nav)
100     * If it is not in the cache, load from network.
101     * Use with {@link #setCacheMode}.
102     */
103    public static final int LOAD_CACHE_ELSE_NETWORK = 1;
104
105    /**
106     * Don't use the cache, load from network
107     * Use with {@link #setCacheMode}.
108     */
109    public static final int LOAD_NO_CACHE = 2;
110
111    /**
112     * Don't use the network, load from cache only.
113     * Use with {@link #setCacheMode}.
114     */
115    public static final int LOAD_CACHE_ONLY = 3;
116
117    public enum RenderPriority {
118        NORMAL,
119        HIGH,
120        LOW
121    }
122
123    // WebView associated with this WebSettings.
124    private WebView mWebView;
125    // BrowserFrame used to access the native frame pointer.
126    private BrowserFrame mBrowserFrame;
127    // Flag to prevent multiple SYNC messages at one time.
128    private boolean mSyncPending = false;
129    // Custom handler that queues messages until the WebCore thread is active.
130    private final EventHandler mEventHandler;
131
132    // Private settings so we don't have to go into native code to
133    // retrieve the values. After setXXX, postSync() needs to be called.
134    //
135    // The default values need to match those in WebSettings.cpp
136    // If the defaults change, please also update the JavaDocs so developers
137    // know what they are.
138    private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
139    private Context         mContext;
140    private TextSize        mTextSize = TextSize.NORMAL;
141    private String          mStandardFontFamily = "sans-serif";
142    private String          mFixedFontFamily = "monospace";
143    private String          mSansSerifFontFamily = "sans-serif";
144    private String          mSerifFontFamily = "serif";
145    private String          mCursiveFontFamily = "cursive";
146    private String          mFantasyFontFamily = "fantasy";
147    private String          mDefaultTextEncoding;
148    private String          mUserAgent;
149    private boolean         mUseDefaultUserAgent;
150    private String          mAcceptLanguage;
151    private int             mMinimumFontSize = 8;
152    private int             mMinimumLogicalFontSize = 8;
153    private int             mDefaultFontSize = 16;
154    private int             mDefaultFixedFontSize = 13;
155    private boolean         mLoadsImagesAutomatically = true;
156    private boolean         mBlockNetworkImage = false;
157    private boolean         mBlockNetworkLoads;
158    private boolean         mJavaScriptEnabled = false;
159    private boolean         mPluginsEnabled = false;
160    private boolean         mJavaScriptCanOpenWindowsAutomatically = false;
161    private boolean         mUseDoubleTree = false;
162    private boolean         mUseWideViewport = false;
163    private boolean         mSupportMultipleWindows = false;
164    private boolean         mShrinksStandaloneImagesToFit = false;
165    // HTML5 API flags
166    private boolean         mAppCacheEnabled = false;
167    private boolean         mDatabaseEnabled = false;
168    private boolean         mDomStorageEnabled = false;
169    private boolean         mWorkersEnabled = false;  // only affects V8.
170    // HTML5 configuration parameters
171    private long            mAppCacheMaxSize = Long.MAX_VALUE;
172    private String          mAppCachePath = "";
173    private String          mDatabasePath = "";
174    // Don't need to synchronize the get/set methods as they
175    // are basic types, also none of these values are used in
176    // native WebCore code.
177    private ZoomDensity     mDefaultZoom = ZoomDensity.MEDIUM;
178    private RenderPriority  mRenderPriority = RenderPriority.NORMAL;
179    private int             mOverrideCacheMode = LOAD_DEFAULT;
180    private boolean         mSaveFormData = true;
181    private boolean         mSavePassword = true;
182    private boolean         mLightTouchEnabled = false;
183    private boolean         mNeedInitialFocus = true;
184    private boolean         mNavDump = false;
185    private boolean         mSupportZoom = true;
186    private boolean         mBuiltInZoomControls = false;
187    private boolean         mAllowFileAccess = true;
188
189    // Class to handle messages before WebCore is ready.
190    private class EventHandler {
191        // Message id for syncing
192        static final int SYNC = 0;
193        // Message id for setting priority
194        static final int PRIORITY = 1;
195        // Actual WebCore thread handler
196        private Handler mHandler;
197
198        private synchronized void createHandler() {
199            // as mRenderPriority can be set before thread is running, sync up
200            setRenderPriority();
201
202            // create a new handler
203            mHandler = new Handler() {
204                @Override
205                public void handleMessage(Message msg) {
206                    switch (msg.what) {
207                        case SYNC:
208                            synchronized (WebSettings.this) {
209                                if (mBrowserFrame.mNativeFrame != 0) {
210                                    nativeSync(mBrowserFrame.mNativeFrame);
211                                }
212                                mSyncPending = false;
213                            }
214                            break;
215
216                        case PRIORITY: {
217                            setRenderPriority();
218                            break;
219                        }
220                    }
221                }
222            };
223        }
224
225        private void setRenderPriority() {
226            synchronized (WebSettings.this) {
227                if (mRenderPriority == RenderPriority.NORMAL) {
228                    android.os.Process.setThreadPriority(
229                            android.os.Process.THREAD_PRIORITY_DEFAULT);
230                } else if (mRenderPriority == RenderPriority.HIGH) {
231                    android.os.Process.setThreadPriority(
232                            android.os.Process.THREAD_PRIORITY_FOREGROUND +
233                            android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
234                } else if (mRenderPriority == RenderPriority.LOW) {
235                    android.os.Process.setThreadPriority(
236                            android.os.Process.THREAD_PRIORITY_BACKGROUND);
237                }
238            }
239        }
240
241        /**
242         * Send a message to the private queue or handler.
243         */
244        private synchronized boolean sendMessage(Message msg) {
245            if (mHandler != null) {
246                mHandler.sendMessage(msg);
247                return true;
248            } else {
249                return false;
250            }
251        }
252    }
253
254    // User agent strings.
255    private static final String DESKTOP_USERAGENT =
256            "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us)"
257            + " AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0"
258            + " Safari/530.17";
259    private static final String IPHONE_USERAGENT =
260            "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)"
261            + " AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0"
262            + " Mobile/7A341 Safari/528.16";
263    private static Locale sLocale;
264    private static Object sLockForLocaleSettings;
265
266    /**
267     * Package constructor to prevent clients from creating a new settings
268     * instance.
269     */
270    WebSettings(Context context, WebView webview) {
271        mEventHandler = new EventHandler();
272        mContext = context;
273        mWebView = webview;
274        mDefaultTextEncoding = context.getString(com.android.internal.
275                                                 R.string.default_text_encoding);
276
277        if (sLockForLocaleSettings == null) {
278            sLockForLocaleSettings = new Object();
279            sLocale = Locale.getDefault();
280        }
281        mAcceptLanguage = getCurrentAcceptLanguage();
282        mUserAgent = getCurrentUserAgent();
283        mUseDefaultUserAgent = true;
284
285        mBlockNetworkLoads = mContext.checkPermission(
286                "android.permission.INTERNET", android.os.Process.myPid(),
287                android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED;
288    }
289
290    /**
291     * Looks at sLocale and returns current AcceptLanguage String.
292     * @return Current AcceptLanguage String.
293     */
294    private String getCurrentAcceptLanguage() {
295        Locale locale;
296        synchronized(sLockForLocaleSettings) {
297            locale = sLocale;
298        }
299        StringBuffer buffer = new StringBuffer();
300        final String language = locale.getLanguage();
301        if (language != null) {
302            buffer.append(language);
303            final String country = locale.getCountry();
304            if (country != null) {
305                buffer.append("-");
306                buffer.append(country);
307            }
308        }
309        if (!locale.equals(Locale.US)) {
310            buffer.append(", ");
311            java.util.Locale us = Locale.US;
312            if (us.getLanguage() != null) {
313                buffer.append(us.getLanguage());
314                final String country = us.getCountry();
315                if (country != null) {
316                    buffer.append("-");
317                    buffer.append(country);
318                }
319            }
320        }
321
322        return buffer.toString();
323    }
324
325    /**
326     * Looks at sLocale and mContext and returns current UserAgent String.
327     * @return Current UserAgent String.
328     */
329    private synchronized String getCurrentUserAgent() {
330        Locale locale;
331        synchronized(sLockForLocaleSettings) {
332            locale = sLocale;
333        }
334        StringBuffer buffer = new StringBuffer();
335        // Add version
336        final String version = Build.VERSION.RELEASE;
337        if (version.length() > 0) {
338            buffer.append(version);
339        } else {
340            // default to "1.0"
341            buffer.append("1.0");
342        }
343        buffer.append("; ");
344        final String language = locale.getLanguage();
345        if (language != null) {
346            buffer.append(language.toLowerCase());
347            final String country = locale.getCountry();
348            if (country != null) {
349                buffer.append("-");
350                buffer.append(country.toLowerCase());
351            }
352        } else {
353            // default to "en"
354            buffer.append("en");
355        }
356
357        final String model = Build.MODEL;
358        if (model.length() > 0) {
359            buffer.append("; ");
360            buffer.append(model);
361        }
362        final String id = Build.ID;
363        if (id.length() > 0) {
364            buffer.append(" Build/");
365            buffer.append(id);
366        }
367        final String base = mContext.getResources().getText(
368                com.android.internal.R.string.web_user_agent).toString();
369        return String.format(base, buffer);
370    }
371
372    /**
373     * Enables dumping the pages navigation cache to a text file.
374     */
375    public void setNavDump(boolean enabled) {
376        mNavDump = enabled;
377    }
378
379    /**
380     * Returns true if dumping the navigation cache is enabled.
381     */
382    public boolean getNavDump() {
383        return mNavDump;
384    }
385
386    /**
387     * Set whether the WebView supports zoom
388     */
389    public void setSupportZoom(boolean support) {
390        mSupportZoom = support;
391    }
392
393    /**
394     * Returns whether the WebView supports zoom
395     */
396    public boolean supportZoom() {
397        return mSupportZoom;
398    }
399
400    /**
401     * Sets whether the zoom mechanism built into WebView is used.
402     */
403    public void setBuiltInZoomControls(boolean enabled) {
404        mBuiltInZoomControls = enabled;
405    }
406
407    /**
408     * Returns true if the zoom mechanism built into WebView is being used.
409     */
410    public boolean getBuiltInZoomControls() {
411        return mBuiltInZoomControls;
412    }
413
414    /**
415     * Enable or disable file access within WebView. File access is enabled by
416     * default.
417     */
418    public void setAllowFileAccess(boolean allow) {
419        mAllowFileAccess = allow;
420    }
421
422    /**
423     * Returns true if this WebView supports file access.
424     */
425    public boolean getAllowFileAccess() {
426        return mAllowFileAccess;
427    }
428
429    /**
430     * Store whether the WebView is saving form data.
431     */
432    public void setSaveFormData(boolean save) {
433        mSaveFormData = save;
434    }
435
436    /**
437     *  Return whether the WebView is saving form data.
438     */
439    public boolean getSaveFormData() {
440        return mSaveFormData;
441    }
442
443    /**
444     *  Store whether the WebView is saving password.
445     */
446    public void setSavePassword(boolean save) {
447        mSavePassword = save;
448    }
449
450    /**
451     *  Return whether the WebView is saving password.
452     */
453    public boolean getSavePassword() {
454        return mSavePassword;
455    }
456
457    /**
458     * Set the text size of the page.
459     * @param t A TextSize value for increasing or decreasing the text.
460     * @see WebSettings.TextSize
461     */
462    public synchronized void setTextSize(TextSize t) {
463        if (WebView.mLogEvent && mTextSize != t ) {
464            Checkin.updateStats(mContext.getContentResolver(),
465                    Checkin.Stats.Tag.BROWSER_TEXT_SIZE_CHANGE, 1, 0.0);
466        }
467        mTextSize = t;
468        postSync();
469    }
470
471    /**
472     * Get the text size of the page.
473     * @return A TextSize enum value describing the text size.
474     * @see WebSettings.TextSize
475     */
476    public synchronized TextSize getTextSize() {
477        return mTextSize;
478    }
479
480    /**
481     * Set the default zoom density of the page. This should be called from UI
482     * thread.
483     * @param zoom A ZoomDensity value
484     * @see WebSettings.ZoomDensity
485     * @hide Pending API council approval
486     */
487    public void setDefaultZoom(ZoomDensity zoom) {
488        if (mDefaultZoom != zoom) {
489            mDefaultZoom = zoom;
490            mWebView.updateDefaultZoomDensity(zoom.value);
491        }
492    }
493
494    /**
495     * Get the default zoom density of the page. This should be called from UI
496     * thread.
497     * @return A ZoomDensity value
498     * @see WebSettings.ZoomDensity
499     * @hide Pending API council approval
500     */
501    public ZoomDensity getDefaultZoom() {
502        return mDefaultZoom;
503    }
504
505    /**
506     * Enables using light touches to make a selection and activate mouseovers.
507     */
508    public void setLightTouchEnabled(boolean enabled) {
509        mLightTouchEnabled = enabled;
510    }
511
512    /**
513     * Returns true if light touches are enabled.
514     */
515    public boolean getLightTouchEnabled() {
516        return mLightTouchEnabled;
517    }
518
519    /**
520     * @deprecated This setting controlled a rendering optimization
521     * that is no longer present. Setting it now has no effect.
522     */
523    @Deprecated
524    public synchronized void setUseDoubleTree(boolean use) {
525        return;
526    }
527
528    /**
529     * @deprecated This setting controlled a rendering optimization
530     * that is no longer present. Setting it now has no effect.
531     */
532    @Deprecated
533    public synchronized boolean getUseDoubleTree() {
534        return false;
535    }
536
537    /**
538     * Tell the WebView about user-agent string.
539     * @param ua 0 if the WebView should use an Android user-agent string,
540     *           1 if the WebView should use a desktop user-agent string.
541     *
542     * @deprecated Please use setUserAgentString instead.
543     */
544    @Deprecated
545    public synchronized void setUserAgent(int ua) {
546        String uaString = null;
547        if (ua == 1) {
548            if (DESKTOP_USERAGENT.equals(mUserAgent)) {
549                return; // do nothing
550            } else {
551                uaString = DESKTOP_USERAGENT;
552            }
553        } else if (ua == 2) {
554            if (IPHONE_USERAGENT.equals(mUserAgent)) {
555                return; // do nothing
556            } else {
557                uaString = IPHONE_USERAGENT;
558            }
559        } else if (ua != 0) {
560            return; // do nothing
561        }
562        setUserAgentString(uaString);
563    }
564
565    /**
566     * Return user-agent as int
567     * @return int  0 if the WebView is using an Android user-agent string.
568     *              1 if the WebView is using a desktop user-agent string.
569     *             -1 if the WebView is using user defined user-agent string.
570     *
571     * @deprecated Please use getUserAgentString instead.
572     */
573    @Deprecated
574    public synchronized int getUserAgent() {
575        if (DESKTOP_USERAGENT.equals(mUserAgent)) {
576            return 1;
577        } else if (IPHONE_USERAGENT.equals(mUserAgent)) {
578            return 2;
579        } else if (mUseDefaultUserAgent) {
580            return 0;
581        }
582        return -1;
583    }
584
585    /**
586     * Tell the WebView to use the wide viewport
587     */
588    public synchronized void setUseWideViewPort(boolean use) {
589        if (mUseWideViewport != use) {
590            mUseWideViewport = use;
591            postSync();
592        }
593    }
594
595    /**
596     * @return True if the WebView is using a wide viewport
597     */
598    public synchronized boolean getUseWideViewPort() {
599        return mUseWideViewport;
600    }
601
602    /**
603     * Tell the WebView whether it supports multiple windows. TRUE means
604     *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
605     *         boolean, Message)} is implemented by the host application.
606     */
607    public synchronized void setSupportMultipleWindows(boolean support) {
608        if (mSupportMultipleWindows != support) {
609            mSupportMultipleWindows = support;
610            postSync();
611        }
612    }
613
614    /**
615     * @return True if the WebView is supporting multiple windows. This means
616     *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
617     *         boolean, Message)} is implemented by the host application.
618     */
619    public synchronized boolean supportMultipleWindows() {
620        return mSupportMultipleWindows;
621    }
622
623    /**
624     * Set the underlying layout algorithm. This will cause a relayout of the
625     * WebView.
626     * @param l A LayoutAlgorithm enum specifying the algorithm to use.
627     * @see WebSettings.LayoutAlgorithm
628     */
629    public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
630        // XXX: This will only be affective if libwebcore was built with
631        // ANDROID_LAYOUT defined.
632        if (mLayoutAlgorithm != l) {
633            mLayoutAlgorithm = l;
634            postSync();
635        }
636    }
637
638    /**
639     * Return the current layout algorithm. The default is NARROW_COLUMNS.
640     * @return LayoutAlgorithm enum value describing the layout algorithm
641     *         being used.
642     * @see WebSettings.LayoutAlgorithm
643     */
644    public synchronized LayoutAlgorithm getLayoutAlgorithm() {
645        return mLayoutAlgorithm;
646    }
647
648    /**
649     * Set the standard font family name.
650     * @param font A font family name.
651     */
652    public synchronized void setStandardFontFamily(String font) {
653        if (font != null && !font.equals(mStandardFontFamily)) {
654            mStandardFontFamily = font;
655            postSync();
656        }
657    }
658
659    /**
660     * Get the standard font family name. The default is "sans-serif".
661     * @return The standard font family name as a string.
662     */
663    public synchronized String getStandardFontFamily() {
664        return mStandardFontFamily;
665    }
666
667    /**
668     * Set the fixed font family name.
669     * @param font A font family name.
670     */
671    public synchronized void setFixedFontFamily(String font) {
672        if (font != null && !font.equals(mFixedFontFamily)) {
673            mFixedFontFamily = font;
674            postSync();
675        }
676    }
677
678    /**
679     * Get the fixed font family name. The default is "monospace".
680     * @return The fixed font family name as a string.
681     */
682    public synchronized String getFixedFontFamily() {
683        return mFixedFontFamily;
684    }
685
686    /**
687     * Set the sans-serif font family name.
688     * @param font A font family name.
689     */
690    public synchronized void setSansSerifFontFamily(String font) {
691        if (font != null && !font.equals(mSansSerifFontFamily)) {
692            mSansSerifFontFamily = font;
693            postSync();
694        }
695    }
696
697    /**
698     * Get the sans-serif font family name.
699     * @return The sans-serif font family name as a string.
700     */
701    public synchronized String getSansSerifFontFamily() {
702        return mSansSerifFontFamily;
703    }
704
705    /**
706     * Set the serif font family name. The default is "sans-serif".
707     * @param font A font family name.
708     */
709    public synchronized void setSerifFontFamily(String font) {
710        if (font != null && !font.equals(mSerifFontFamily)) {
711            mSerifFontFamily = font;
712            postSync();
713        }
714    }
715
716    /**
717     * Get the serif font family name. The default is "serif".
718     * @return The serif font family name as a string.
719     */
720    public synchronized String getSerifFontFamily() {
721        return mSerifFontFamily;
722    }
723
724    /**
725     * Set the cursive font family name.
726     * @param font A font family name.
727     */
728    public synchronized void setCursiveFontFamily(String font) {
729        if (font != null && !font.equals(mCursiveFontFamily)) {
730            mCursiveFontFamily = font;
731            postSync();
732        }
733    }
734
735    /**
736     * Get the cursive font family name. The default is "cursive".
737     * @return The cursive font family name as a string.
738     */
739    public synchronized String getCursiveFontFamily() {
740        return mCursiveFontFamily;
741    }
742
743    /**
744     * Set the fantasy font family name.
745     * @param font A font family name.
746     */
747    public synchronized void setFantasyFontFamily(String font) {
748        if (font != null && !font.equals(mFantasyFontFamily)) {
749            mFantasyFontFamily = font;
750            postSync();
751        }
752    }
753
754    /**
755     * Get the fantasy font family name. The default is "fantasy".
756     * @return The fantasy font family name as a string.
757     */
758    public synchronized String getFantasyFontFamily() {
759        return mFantasyFontFamily;
760    }
761
762    /**
763     * Set the minimum font size.
764     * @param size A non-negative integer between 1 and 72.
765     * Any number outside the specified range will be pinned.
766     */
767    public synchronized void setMinimumFontSize(int size) {
768        size = pin(size);
769        if (mMinimumFontSize != size) {
770            mMinimumFontSize = size;
771            postSync();
772        }
773    }
774
775    /**
776     * Get the minimum font size. The default is 8.
777     * @return A non-negative integer between 1 and 72.
778     */
779    public synchronized int getMinimumFontSize() {
780        return mMinimumFontSize;
781    }
782
783    /**
784     * Set the minimum logical font size.
785     * @param size A non-negative integer between 1 and 72.
786     * Any number outside the specified range will be pinned.
787     */
788    public synchronized void setMinimumLogicalFontSize(int size) {
789        size = pin(size);
790        if (mMinimumLogicalFontSize != size) {
791            mMinimumLogicalFontSize = size;
792            postSync();
793        }
794    }
795
796    /**
797     * Get the minimum logical font size. The default is 8.
798     * @return A non-negative integer between 1 and 72.
799     */
800    public synchronized int getMinimumLogicalFontSize() {
801        return mMinimumLogicalFontSize;
802    }
803
804    /**
805     * Set the default font size.
806     * @param size A non-negative integer between 1 and 72.
807     * Any number outside the specified range will be pinned.
808     */
809    public synchronized void setDefaultFontSize(int size) {
810        size = pin(size);
811        if (mDefaultFontSize != size) {
812            mDefaultFontSize = size;
813            postSync();
814        }
815    }
816
817    /**
818     * Get the default font size. The default is 16.
819     * @return A non-negative integer between 1 and 72.
820     */
821    public synchronized int getDefaultFontSize() {
822        return mDefaultFontSize;
823    }
824
825    /**
826     * Set the default fixed font size.
827     * @param size A non-negative integer between 1 and 72.
828     * Any number outside the specified range will be pinned.
829     */
830    public synchronized void setDefaultFixedFontSize(int size) {
831        size = pin(size);
832        if (mDefaultFixedFontSize != size) {
833            mDefaultFixedFontSize = size;
834            postSync();
835        }
836    }
837
838    /**
839     * Get the default fixed font size. The default is 16.
840     * @return A non-negative integer between 1 and 72.
841     */
842    public synchronized int getDefaultFixedFontSize() {
843        return mDefaultFixedFontSize;
844    }
845
846    /**
847     * Tell the WebView to load image resources automatically.
848     * @param flag True if the WebView should load images automatically.
849     */
850    public synchronized void setLoadsImagesAutomatically(boolean flag) {
851        if (mLoadsImagesAutomatically != flag) {
852            mLoadsImagesAutomatically = flag;
853            postSync();
854        }
855    }
856
857    /**
858     * Return true if the WebView will load image resources automatically.
859     * The default is true.
860     * @return True if the WebView loads images automatically.
861     */
862    public synchronized boolean getLoadsImagesAutomatically() {
863        return mLoadsImagesAutomatically;
864    }
865
866    /**
867     * Tell the WebView to block network image. This is only checked when
868     * getLoadsImagesAutomatically() is true.
869     * @param flag True if the WebView should block network image
870     */
871    public synchronized void setBlockNetworkImage(boolean flag) {
872        if (mBlockNetworkImage != flag) {
873            mBlockNetworkImage = flag;
874            postSync();
875        }
876    }
877
878    /**
879     * Return true if the WebView will block network image. The default is false.
880     * @return True if the WebView blocks network image.
881     */
882    public synchronized boolean getBlockNetworkImage() {
883        return mBlockNetworkImage;
884    }
885
886    /**
887     * @hide
888     * Tell the WebView to block all network load requests.
889     * @param flag True if the WebView should block all network loads
890     */
891    public synchronized void setBlockNetworkLoads(boolean flag) {
892        if (mBlockNetworkLoads != flag) {
893            mBlockNetworkLoads = flag;
894            verifyNetworkAccess();
895        }
896    }
897
898    /**
899     * @hide
900     * Return true if the WebView will block all network loads.
901     * The default is false.
902     * @return True if the WebView blocks all network loads.
903     */
904    public synchronized boolean getBlockNetworkLoads() {
905        return mBlockNetworkLoads;
906    }
907
908
909    private void verifyNetworkAccess() {
910        if (!mBlockNetworkLoads) {
911            if (mContext.checkPermission("android.permission.INTERNET",
912                    android.os.Process.myPid(), android.os.Process.myUid()) !=
913                        PackageManager.PERMISSION_GRANTED) {
914                throw new SecurityException
915                        ("Permission denied - " +
916                                "application missing INTERNET permission");
917            }
918        }
919    }
920
921    /**
922     * Tell the WebView to enable javascript execution.
923     * @param flag True if the WebView should execute javascript.
924     */
925    public synchronized void setJavaScriptEnabled(boolean flag) {
926        if (mJavaScriptEnabled != flag) {
927            mJavaScriptEnabled = flag;
928            postSync();
929        }
930    }
931
932    /**
933     * Tell the WebView to enable plugins.
934     * @param flag True if the WebView should load plugins.
935     */
936    public synchronized void setPluginsEnabled(boolean flag) {
937        if (mPluginsEnabled != flag) {
938            mPluginsEnabled = flag;
939            postSync();
940        }
941    }
942
943    /**
944     * TODO: need to add @Deprecated
945     */
946    public synchronized void setPluginsPath(String pluginsPath) {
947    }
948
949    /**
950     * Set the path to where database storage API databases should be saved.
951     * This will update WebCore when the Sync runs in the C++ side.
952     * @param databasePath String path to the directory where databases should
953     *     be saved. May be the empty string but should never be null.
954     */
955    public synchronized void setDatabasePath(String databasePath) {
956        if (databasePath != null && !databasePath.equals(mDatabasePath)) {
957            mDatabasePath = databasePath;
958            postSync();
959        }
960    }
961
962    /**
963     * Tell the WebView to enable Application Caches API.
964     * @param flag True if the WebView should enable Application Caches.
965     * @hide pending api council approval
966     */
967    public synchronized void setAppCacheEnabled(boolean flag) {
968        if (mAppCacheEnabled != flag) {
969            mAppCacheEnabled = flag;
970            postSync();
971        }
972    }
973
974    /**
975     * Set a custom path to the Application Caches files. The client
976     * must ensure it exists before this call.
977     * @param appCachePath String path to the directory containing Application
978     * Caches files. The appCache path can be the empty string but should not
979     * be null. Passing null for this parameter will result in a no-op.
980     * @hide pending api council approval
981     */
982    public synchronized void setAppCachePath(String appCachePath) {
983        if (appCachePath != null && !appCachePath.equals(mAppCachePath)) {
984            mAppCachePath = appCachePath;
985            postSync();
986        }
987    }
988
989    /**
990     * Set the maximum size for the Application Caches content.
991     * @param appCacheMaxSize the maximum size in bytes.
992     *
993     * @hide pending api council approval
994     */
995    public synchronized void setAppCacheMaxSize(long appCacheMaxSize) {
996        if (appCacheMaxSize != mAppCacheMaxSize) {
997            mAppCacheMaxSize = appCacheMaxSize;
998            postSync();
999        }
1000    }
1001
1002    /**
1003     * Set whether the database storage API is enabled.
1004     * @param flag boolean True if the WebView should use the database storage
1005     *     API.
1006     */
1007    public synchronized void setDatabaseEnabled(boolean flag) {
1008       if (mDatabaseEnabled != flag) {
1009           mDatabaseEnabled = flag;
1010           postSync();
1011       }
1012    }
1013
1014    /**
1015     * Set whether the DOM storage API is enabled.
1016     * @param flag boolean True if the WebView should use the DOM storage
1017     *     API.
1018     * @hide pending API council.
1019     */
1020    public synchronized void setDomStorageEnabled(boolean flag) {
1021       if (mDomStorageEnabled != flag) {
1022           mDomStorageEnabled = flag;
1023           postSync();
1024       }
1025    }
1026
1027    /**
1028     * Returns true if the DOM Storage API's are enabled.
1029     * @return True if the DOM Storage API's are enabled.
1030     * @hide pending API council.
1031     */
1032    public synchronized boolean getDomStorageEnabled() {
1033       return mDomStorageEnabled;
1034    }
1035
1036    /**
1037     * Return the path to where database storage API databases are saved for
1038     * the current WebView.
1039     * @return the String path to the database storage API databases.
1040     */
1041    public synchronized String getDatabasePath() {
1042        return mDatabasePath;
1043    }
1044
1045    /**
1046     * Returns true if database storage API is enabled.
1047     * @return True if the database storage API is enabled.
1048     */
1049    public synchronized boolean getDatabaseEnabled() {
1050        return mDatabaseEnabled;
1051    }
1052
1053    /**
1054     * Tell the WebView to enable WebWorkers API.
1055     * @param flag True if the WebView should enable WebWorkers.
1056     * Note that this flag only affects V8. JSC does not have
1057     * an equivalent setting.
1058     * @hide pending api council approval
1059     */
1060    public synchronized void setWorkersEnabled(boolean flag) {
1061        if (mWorkersEnabled != flag) {
1062            mWorkersEnabled = flag;
1063            postSync();
1064        }
1065    }
1066
1067    /**
1068     * Return true if javascript is enabled. <b>Note: The default is false.</b>
1069     * @return True if javascript is enabled.
1070     */
1071    public synchronized boolean getJavaScriptEnabled() {
1072        return mJavaScriptEnabled;
1073    }
1074
1075    /**
1076     * Return true if plugins are enabled.
1077     * @return True if plugins are enabled.
1078     */
1079    public synchronized boolean getPluginsEnabled() {
1080        return mPluginsEnabled;
1081    }
1082
1083    /**
1084     * TODO: need to add @Deprecated
1085     */
1086    public synchronized String getPluginsPath() {
1087        return "";
1088    }
1089
1090    /**
1091     * Tell javascript to open windows automatically. This applies to the
1092     * javascript function window.open().
1093     * @param flag True if javascript can open windows automatically.
1094     */
1095    public synchronized void setJavaScriptCanOpenWindowsAutomatically(
1096            boolean flag) {
1097        if (mJavaScriptCanOpenWindowsAutomatically != flag) {
1098            mJavaScriptCanOpenWindowsAutomatically = flag;
1099            postSync();
1100        }
1101    }
1102
1103    /**
1104     * Return true if javascript can open windows automatically. The default
1105     * is false.
1106     * @return True if javascript can open windows automatically during
1107     *         window.open().
1108     */
1109    public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() {
1110        return mJavaScriptCanOpenWindowsAutomatically;
1111    }
1112
1113    /**
1114     * Set the default text encoding name to use when decoding html pages.
1115     * @param encoding The text encoding name.
1116     */
1117    public synchronized void setDefaultTextEncodingName(String encoding) {
1118        if (encoding != null && !encoding.equals(mDefaultTextEncoding)) {
1119            mDefaultTextEncoding = encoding;
1120            postSync();
1121        }
1122    }
1123
1124    /**
1125     * Get the default text encoding name. The default is "Latin-1".
1126     * @return The default text encoding name as a string.
1127     */
1128    public synchronized String getDefaultTextEncodingName() {
1129        return mDefaultTextEncoding;
1130    }
1131
1132    /**
1133     * Set the WebView's user-agent string. If the string "ua" is null or empty,
1134     * it will use the system default user-agent string.
1135     */
1136    public synchronized void setUserAgentString(String ua) {
1137        if (ua == null || ua.length() == 0) {
1138            synchronized(sLockForLocaleSettings) {
1139                Locale currentLocale = Locale.getDefault();
1140                if (!sLocale.equals(currentLocale)) {
1141                    sLocale = currentLocale;
1142                    mAcceptLanguage = getCurrentAcceptLanguage();
1143                }
1144            }
1145            ua = getCurrentUserAgent();
1146            mUseDefaultUserAgent = true;
1147        } else  {
1148            mUseDefaultUserAgent = false;
1149        }
1150
1151        if (!ua.equals(mUserAgent)) {
1152            mUserAgent = ua;
1153            postSync();
1154        }
1155    }
1156
1157    /**
1158     * Return the WebView's user-agent string.
1159     */
1160    public synchronized String getUserAgentString() {
1161        if (DESKTOP_USERAGENT.equals(mUserAgent) ||
1162                IPHONE_USERAGENT.equals(mUserAgent) ||
1163                !mUseDefaultUserAgent) {
1164            return mUserAgent;
1165        }
1166
1167        boolean doPostSync = false;
1168        synchronized(sLockForLocaleSettings) {
1169            Locale currentLocale = Locale.getDefault();
1170            if (!sLocale.equals(currentLocale)) {
1171                sLocale = currentLocale;
1172                mUserAgent = getCurrentUserAgent();
1173                mAcceptLanguage = getCurrentAcceptLanguage();
1174                doPostSync = true;
1175            }
1176        }
1177        if (doPostSync) {
1178            postSync();
1179        }
1180        return mUserAgent;
1181    }
1182
1183    /* package api to grab the Accept Language string. */
1184    /*package*/ synchronized String getAcceptLanguage() {
1185        synchronized(sLockForLocaleSettings) {
1186            Locale currentLocale = Locale.getDefault();
1187            if (!sLocale.equals(currentLocale)) {
1188                sLocale = currentLocale;
1189                mAcceptLanguage = getCurrentAcceptLanguage();
1190            }
1191        }
1192        return mAcceptLanguage;
1193    }
1194
1195    /**
1196     * Tell the WebView whether it needs to set a node to have focus when
1197     * {@link WebView#requestFocus(int, android.graphics.Rect)} is called.
1198     *
1199     * @param flag
1200     */
1201    public void setNeedInitialFocus(boolean flag) {
1202        if (mNeedInitialFocus != flag) {
1203            mNeedInitialFocus = flag;
1204        }
1205    }
1206
1207    /* Package api to get the choice whether it needs to set initial focus. */
1208    /* package */ boolean getNeedInitialFocus() {
1209        return mNeedInitialFocus;
1210    }
1211
1212    /**
1213     * Set the priority of the Render thread. Unlike the other settings, this
1214     * one only needs to be called once per process. The default is NORMAL.
1215     *
1216     * @param priority RenderPriority, can be normal, high or low.
1217     */
1218    public synchronized void setRenderPriority(RenderPriority priority) {
1219        if (mRenderPriority != priority) {
1220            mRenderPriority = priority;
1221            mEventHandler.sendMessage(Message.obtain(null,
1222                    EventHandler.PRIORITY));
1223        }
1224    }
1225
1226    /**
1227     * Override the way the cache is used. The way the cache is used is based
1228     * on the navigation option. For a normal page load, the cache is checked
1229     * and content is re-validated as needed. When navigating back, content is
1230     * not revalidated, instead the content is just pulled from the cache.
1231     * This function allows the client to override this behavior.
1232     * @param mode One of the LOAD_ values.
1233     */
1234    public void setCacheMode(int mode) {
1235        if (mode != mOverrideCacheMode) {
1236            mOverrideCacheMode = mode;
1237        }
1238    }
1239
1240    /**
1241     * Return the current setting for overriding the cache mode. For a full
1242     * description, see the {@link #setCacheMode(int)} function.
1243     */
1244    public int getCacheMode() {
1245        return mOverrideCacheMode;
1246    }
1247
1248    /**
1249     * If set, webkit alternately shrinks and expands images viewed outside
1250     * of an HTML page to fit the screen. This conflicts with attempts by
1251     * the UI to zoom in and out of an image, so it is set false by default.
1252     * @param shrink Set true to let webkit shrink the standalone image to fit.
1253     * {@hide}
1254     */
1255    public void setShrinksStandaloneImagesToFit(boolean shrink) {
1256        if (mShrinksStandaloneImagesToFit != shrink) {
1257            mShrinksStandaloneImagesToFit = shrink;
1258            postSync();
1259        }
1260     }
1261
1262    /**
1263     * Transfer messages from the queue to the new WebCoreThread. Called from
1264     * WebCore thread.
1265     */
1266    /*package*/
1267    synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
1268        mBrowserFrame = frame;
1269        if (DebugFlags.WEB_SETTINGS) {
1270            junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
1271        }
1272        nativeSync(frame.mNativeFrame);
1273        mSyncPending = false;
1274        mEventHandler.createHandler();
1275    }
1276
1277    private int pin(int size) {
1278        // FIXME: 72 is just an arbitrary max text size value.
1279        if (size < 1) {
1280            return 1;
1281        } else if (size > 72) {
1282            return 72;
1283        }
1284        return size;
1285    }
1286
1287    /* Post a SYNC message to handle syncing the native settings. */
1288    private synchronized void postSync() {
1289        // Only post if a sync is not pending
1290        if (!mSyncPending) {
1291            mSyncPending = mEventHandler.sendMessage(
1292                    Message.obtain(null, EventHandler.SYNC));
1293        }
1294    }
1295
1296    // Synchronize the native and java settings.
1297    private native void nativeSync(int nativeFrame);
1298}
1299