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