ContentSettings.java revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.content.browser;
6
7import android.os.Handler;
8import android.os.Looper;
9import android.os.Message;
10import android.webkit.WebSettings.PluginState;
11import android.webkit.WebView;
12
13import org.chromium.base.CalledByNative;
14import org.chromium.base.JNINamespace;
15import org.chromium.base.ThreadUtils;
16
17/**
18 * Manages settings state for a ContentView. A ContentSettings instance is obtained
19 * from ContentView.getContentSettings(). If ContentView is used in the
20 * ContentView.PERSONALITY_VIEW role, all settings are read / write. If ContentView
21 * is in the ContentView.PERSONALITY_CHROME role, setting can only be read.
22 */
23@JNINamespace("content")
24public class ContentSettings {
25    private static final String TAG = "ContentSettings";
26
27    // This class must be created on the UI thread. Afterwards, it can be
28    // used from any thread. Internally, the class uses a message queue
29    // to call native code on the UI thread only.
30
31    // The native side of this object. Ownership is retained native-side by the WebContents
32    // instance that backs the associated ContentViewCore.
33    private int mNativeContentSettings = 0;
34
35    private ContentViewCore mContentViewCore;
36
37    // When ContentView is used in PERSONALITY_CHROME mode, settings can't
38    // be modified through the ContentSettings instance.
39    private boolean mCanModifySettings;
40
41    // A flag to avoid sending superfluous synchronization messages.
42    private boolean mIsSyncMessagePending = false;
43    // Custom handler that queues messages to call native code on the UI thread.
44    private final EventHandler mEventHandler;
45
46    // Protects access to settings fields.
47    private final Object mContentSettingsLock = new Object();
48
49    private static final int MINIMUM_FONT_SIZE = 1;
50    private static final int MAXIMUM_FONT_SIZE = 72;
51
52    // Private settings so we don't have to go into native code to
53    // retrieve the values. After setXXX, mEventHandler.syncSettingsLocked() needs to be called.
54    //
55    // TODO(mnaganov): populate with the complete set of legacy WebView settings.
56
57    private int mTextSizePercent = 100;
58    private String mStandardFontFamily = "sans-serif";
59    private String mFixedFontFamily = "monospace";
60    private String mSansSerifFontFamily = "sans-serif";
61    private String mSerifFontFamily = "serif";
62    private String mCursiveFontFamily = "cursive";
63    private String mFantasyFontFamily = "fantasy";
64    // FIXME: Should be obtained from Android. Problem: it is hidden.
65    private String mDefaultTextEncoding = "Latin-1";
66    private String mUserAgent;
67    private int mMinimumFontSize = 8;
68    private int mMinimumLogicalFontSize = 8;
69    private int mDefaultFontSize = 16;
70    private int mDefaultFixedFontSize = 13;
71    private boolean mLoadsImagesAutomatically = true;
72    private boolean mImagesEnabled = true;
73    private boolean mJavaScriptEnabled = false;
74    private boolean mAllowUniversalAccessFromFileURLs = false;
75    private boolean mAllowFileAccessFromFileURLs = false;
76    private boolean mJavaScriptCanOpenWindowsAutomatically = false;
77    private boolean mSupportMultipleWindows = false;
78    private PluginState mPluginState = PluginState.OFF;
79    private boolean mDomStorageEnabled = false;
80
81    // Not accessed by the native side.
82    private String mDefaultUserAgent = "";
83    private boolean mSupportZoom = true;
84    private boolean mBuiltInZoomControls = false;
85    private boolean mDisplayZoomControls = true;
86
87    // Class to handle messages to be processed on the UI thread.
88    private class EventHandler {
89        // Message id for syncing
90        private static final int SYNC = 0;
91        // Message id for updating user agent in the view
92        private static final int UPDATE_UA = 1;
93        // Message id for updating multi-touch zoom state in the view
94        private static final int UPDATE_MULTI_TOUCH = 2;
95        // Actual UI thread handler
96        private Handler mHandler;
97
98        EventHandler() {
99            mHandler = mContentViewCore.isPersonalityView() ?
100                    new Handler(Looper.getMainLooper()) {
101                        @Override
102                        public void handleMessage(Message msg) {
103                            switch (msg.what) {
104                                case SYNC:
105                                    synchronized (mContentSettingsLock) {
106                                        syncToNativeOnUiThread();
107                                        mIsSyncMessagePending = false;
108                                        mContentSettingsLock.notifyAll();
109                                    }
110                                    break;
111                                case UPDATE_UA:
112                                    mContentViewCore.setAllUserAgentOverridesInHistory();
113                                    break;
114                                case UPDATE_MULTI_TOUCH:
115                                    mContentViewCore.updateMultiTouchZoomSupport();
116                                    break;
117                            }
118                        }
119                    } :
120                    new Handler(Looper.getMainLooper()) {
121                        @Override
122                        public void handleMessage(Message msg) {
123                            switch (msg.what) {
124                                case SYNC:
125                                    synchronized (mContentSettingsLock) {
126                                        syncFromNativeOnUiThread();
127                                        mIsSyncMessagePending = false;
128                                    }
129                                    break;
130                            }
131                        }
132                    };
133        }
134
135        private void syncSettingsLocked() {
136            assert Thread.holdsLock(mContentSettingsLock);
137            if (mNativeContentSettings == 0) return;
138            if (mContentViewCore.isPersonalityView()) {
139                if (Looper.myLooper() == mHandler.getLooper()) {
140                    syncToNativeOnUiThread();
141                } else {
142                    // We're being called on a background thread, so post a message.
143                    if (mIsSyncMessagePending) {
144                        return;
145                    }
146                    mIsSyncMessagePending = true;
147                    mHandler.sendMessage(Message.obtain(null, SYNC));
148                    // When used in PERSONALITY_VIEW mode, we must block
149                    // until the settings have been sync'd to native to
150                    // ensure that they have taken effect.
151                    try {
152                        while (mIsSyncMessagePending) {
153                            mContentSettingsLock.wait();
154                        }
155                    } catch (InterruptedException e) {}
156                }
157            } else {
158                if (mIsSyncMessagePending) {
159                    return;
160                }
161                mIsSyncMessagePending = true;
162                mHandler.sendMessage(Message.obtain(null, SYNC));
163            }
164        }
165
166        private void sendUpdateUaMessageLocked() {
167            assert Thread.holdsLock(mContentSettingsLock);
168            if (mNativeContentSettings == 0) return;
169            mHandler.sendMessage(Message.obtain(null, UPDATE_UA));
170        }
171
172        private void sendUpdateMultiTouchMessageLocked() {
173            assert Thread.holdsLock(mContentSettingsLock);
174            if (mNativeContentSettings == 0) return;
175            mHandler.sendMessage(Message.obtain(null, UPDATE_MULTI_TOUCH));
176        }
177    }
178
179    /**
180     * Package constructor to prevent clients from creating a new settings
181     * instance. Must be called on the UI thread.
182     */
183    ContentSettings(ContentViewCore contentViewCore, int nativeContentView,
184            boolean isAccessFromFileURLsGrantedByDefault) {
185        ThreadUtils.assertOnUiThread();
186        mContentViewCore = contentViewCore;
187        mCanModifySettings = mContentViewCore.isPersonalityView();
188        mNativeContentSettings = nativeInit(nativeContentView, mCanModifySettings);
189        assert mNativeContentSettings != 0;
190
191        if (isAccessFromFileURLsGrantedByDefault) {
192            mAllowUniversalAccessFromFileURLs = true;
193            mAllowFileAccessFromFileURLs = true;
194        }
195
196        mEventHandler = new EventHandler();
197        if (mCanModifySettings) {
198            // PERSONALITY_VIEW
199            mDefaultUserAgent = nativeGetDefaultUserAgent();
200            mUserAgent = mDefaultUserAgent;
201            syncToNativeOnUiThread();
202        } else {
203            // PERSONALITY_CHROME
204            // Chrome has zooming enabled by default. These settings are not
205            // set by the native code.
206            mBuiltInZoomControls = true;
207            mDisplayZoomControls = false;
208            syncFromNativeOnUiThread();
209        }
210    }
211
212    /**
213     * Notification from the native side that it is being destroyed.
214     * @param nativeContentSettings the native instance that is going away.
215     */
216    @CalledByNative
217    private void onNativeContentSettingsDestroyed(int nativeContentSettings) {
218        assert mNativeContentSettings == nativeContentSettings;
219        mNativeContentSettings = 0;
220    }
221
222    /**
223     * @returns the default User-Agent used by each ContentViewCore instance, i.e. unless
224     * overridden by {@link #setUserAgentString()}
225     */
226    public static String getDefaultUserAgent() {
227        return nativeGetDefaultUserAgent();
228    }
229
230    /**
231     * Set the WebView's user-agent string. If the string "ua" is null or empty,
232     * it will use the system default user-agent string.
233     */
234    public void setUserAgentString(String ua) {
235        assert mCanModifySettings;
236        synchronized (mContentSettingsLock) {
237            final String oldUserAgent = mUserAgent;
238            if (ua == null || ua.length() == 0) {
239                mUserAgent = mDefaultUserAgent;
240            } else {
241                mUserAgent = ua;
242            }
243            if (!oldUserAgent.equals(mUserAgent)) {
244                mEventHandler.sendUpdateUaMessageLocked();
245            }
246        }
247    }
248
249    /**
250     * Gets the WebView's user-agent string.
251     */
252    public String getUserAgentString() {
253        // TODO(mnaganov): Doesn't reflect changes made by ChromeNativePreferences.
254        synchronized (mContentSettingsLock) {
255            return mUserAgent;
256        }
257    }
258
259    /**
260     * Sets whether the WebView should support zooming using its on-screen zoom
261     * controls and gestures. The particular zoom mechanisms that should be used
262     * can be set with {@link #setBuiltInZoomControls}. This setting does not
263     * affect zooming performed using the {@link WebView#zoomIn()} and
264     * {@link WebView#zoomOut()} methods. The default is true.
265     *
266     * @param support whether the WebView should support zoom
267     */
268    public void setSupportZoom(boolean support) {
269        synchronized (mContentSettingsLock) {
270            mSupportZoom = support;
271            mEventHandler.sendUpdateMultiTouchMessageLocked();
272        }
273    }
274
275    /**
276     * Gets whether the WebView supports zoom.
277     *
278     * @return true if the WebView supports zoom
279     * @see #setSupportZoom
280     */
281    public boolean supportZoom() {
282        return mSupportZoom;
283    }
284
285   /**
286     * Sets whether the WebView should use its built-in zoom mechanisms. The
287     * built-in zoom mechanisms comprise on-screen zoom controls, which are
288     * displayed over the WebView's content, and the use of a pinch gesture to
289     * control zooming. Whether or not these on-screen controls are displayed
290     * can be set with {@link #setDisplayZoomControls}. The default is false,
291     * due to compatibility reasons.
292     * <p>
293     * The built-in mechanisms are the only currently supported zoom
294     * mechanisms, so it is recommended that this setting is always enabled.
295     * In other words, there is no point of calling this method other than
296     * with the 'true' parameter.
297     *
298     * @param enabled whether the WebView should use its built-in zoom mechanisms
299     */
300     public void setBuiltInZoomControls(boolean enabled) {
301        synchronized (mContentSettingsLock) {
302            mBuiltInZoomControls = enabled;
303            mEventHandler.sendUpdateMultiTouchMessageLocked();
304        }
305    }
306
307    /**
308     * Gets whether the zoom mechanisms built into WebView are being used.
309     *
310     * @return true if the zoom mechanisms built into WebView are being used
311     * @see #setBuiltInZoomControls
312     */
313    public boolean getBuiltInZoomControls() {
314        return mBuiltInZoomControls;
315    }
316
317    /**
318     * Sets whether the WebView should display on-screen zoom controls when
319     * using the built-in zoom mechanisms. See {@link #setBuiltInZoomControls}.
320     * The default is true.
321     *
322     * @param enabled whether the WebView should display on-screen zoom controls
323     */
324    public void setDisplayZoomControls(boolean enabled) {
325        synchronized (mContentSettingsLock) {
326            mDisplayZoomControls = enabled;
327            mEventHandler.sendUpdateMultiTouchMessageLocked();
328        }
329    }
330
331    /**
332     * Gets whether the WebView displays on-screen zoom controls when using
333     * the built-in zoom mechanisms.
334     *
335     * @return true if the WebView displays on-screen zoom controls when using
336     *         the built-in zoom mechanisms
337     * @see #setDisplayZoomControls
338     */
339    public boolean getDisplayZoomControls() {
340        return mDisplayZoomControls;
341    }
342
343    boolean supportsMultiTouchZoom() {
344        return mSupportZoom && mBuiltInZoomControls;
345    }
346
347    boolean shouldDisplayZoomControls() {
348        return supportsMultiTouchZoom() && mDisplayZoomControls;
349    }
350
351    /**
352     * Sets the text zoom of the page in percent. Default is 100.
353     *
354     * @param textZoom the percent value for increasing or decreasing the text
355     */
356    public void setTextZoom(int textZoom) {
357        assert mCanModifySettings;
358        synchronized (mContentSettingsLock) {
359            if (mTextSizePercent != textZoom) {
360                mTextSizePercent = textZoom;
361                mEventHandler.syncSettingsLocked();
362            }
363        }
364    }
365
366    /**
367     * Gets the text zoom of the page in percent.
368     *
369     * @return a percent value describing the text zoom
370     * @see #setTextSizeZoom
371     */
372    public int getTextZoom() {
373        synchronized (mContentSettingsLock) {
374            return mTextSizePercent;
375        }
376    }
377
378    /**
379     * Set the standard font family name.
380     * @param font A font family name.
381     */
382    public void setStandardFontFamily(String font) {
383        assert mCanModifySettings;
384        synchronized (mContentSettingsLock) {
385            if (!mStandardFontFamily.equals(font)) {
386                mStandardFontFamily = font;
387                mEventHandler.syncSettingsLocked();
388            }
389        }
390    }
391
392    /**
393     * Get the standard font family name. The default is "sans-serif".
394     * @return The standard font family name as a string.
395     */
396    public String getStandardFontFamily() {
397        synchronized (mContentSettingsLock) {
398            return mStandardFontFamily;
399        }
400    }
401
402    /**
403     * Set the fixed font family name.
404     * @param font A font family name.
405     */
406    public void setFixedFontFamily(String font) {
407        assert mCanModifySettings;
408        synchronized (mContentSettingsLock) {
409            if (!mFixedFontFamily.equals(font)) {
410                mFixedFontFamily = font;
411                mEventHandler.syncSettingsLocked();
412            }
413        }
414    }
415
416    /**
417     * Get the fixed font family name. The default is "monospace".
418     * @return The fixed font family name as a string.
419     */
420    public String getFixedFontFamily() {
421        synchronized (mContentSettingsLock) {
422            return mFixedFontFamily;
423        }
424    }
425
426    /**
427     * Set the sans-serif font family name.
428     * @param font A font family name.
429     */
430    public void setSansSerifFontFamily(String font) {
431        assert mCanModifySettings;
432        synchronized (mContentSettingsLock) {
433            if (!mSansSerifFontFamily.equals(font)) {
434                mSansSerifFontFamily = font;
435                mEventHandler.syncSettingsLocked();
436            }
437        }
438    }
439
440    /**
441     * Get the sans-serif font family name.
442     * @return The sans-serif font family name as a string.
443     */
444    public String getSansSerifFontFamily() {
445        synchronized (mContentSettingsLock) {
446            return mSansSerifFontFamily;
447        }
448    }
449
450    /**
451     * Set the serif font family name. The default is "sans-serif".
452     * @param font A font family name.
453     */
454    public void setSerifFontFamily(String font) {
455        assert mCanModifySettings;
456        synchronized (mContentSettingsLock) {
457            if (!mSerifFontFamily.equals(font)) {
458                mSerifFontFamily = font;
459                mEventHandler.syncSettingsLocked();
460            }
461        }
462    }
463
464    /**
465     * Get the serif font family name. The default is "serif".
466     * @return The serif font family name as a string.
467     */
468    public String getSerifFontFamily() {
469        synchronized (mContentSettingsLock) {
470            return mSerifFontFamily;
471        }
472    }
473
474    /**
475     * Set the cursive font family name.
476     * @param font A font family name.
477     */
478    public void setCursiveFontFamily(String font) {
479        assert mCanModifySettings;
480        synchronized (mContentSettingsLock) {
481            if (!mCursiveFontFamily.equals(font)) {
482                mCursiveFontFamily = font;
483                mEventHandler.syncSettingsLocked();
484            }
485        }
486    }
487
488    /**
489     * Get the cursive font family name. The default is "cursive".
490     * @return The cursive font family name as a string.
491     */
492    public String getCursiveFontFamily() {
493        synchronized (mContentSettingsLock) {
494            return mCursiveFontFamily;
495        }
496    }
497
498    /**
499     * Set the fantasy font family name.
500     * @param font A font family name.
501     */
502    public void setFantasyFontFamily(String font) {
503        assert mCanModifySettings;
504        synchronized (mContentSettingsLock) {
505            if (!mFantasyFontFamily.equals(font)) {
506                mFantasyFontFamily = font;
507                mEventHandler.syncSettingsLocked();
508            }
509        }
510    }
511
512    /**
513     * Get the fantasy font family name. The default is "fantasy".
514     * @return The fantasy font family name as a string.
515     */
516    public String getFantasyFontFamily() {
517        synchronized (mContentSettingsLock) {
518            return mFantasyFontFamily;
519        }
520    }
521
522    /**
523     * Set the minimum font size.
524     * @param size A non-negative integer between 1 and 72.
525     * Any number outside the specified range will be pinned.
526     */
527    public void setMinimumFontSize(int size) {
528        assert mCanModifySettings;
529        synchronized (mContentSettingsLock) {
530            size = clipFontSize(size);
531            if (mMinimumFontSize != size) {
532                mMinimumFontSize = size;
533                mEventHandler.syncSettingsLocked();
534            }
535        }
536    }
537
538    /**
539     * Get the minimum font size. The default is 8.
540     * @return A non-negative integer between 1 and 72.
541     */
542    public int getMinimumFontSize() {
543        synchronized (mContentSettingsLock) {
544            return mMinimumFontSize;
545        }
546    }
547
548    /**
549     * Set the minimum logical font size.
550     * @param size A non-negative integer between 1 and 72.
551     * Any number outside the specified range will be pinned.
552     */
553    public void setMinimumLogicalFontSize(int size) {
554        assert mCanModifySettings;
555        synchronized (mContentSettingsLock) {
556            size = clipFontSize(size);
557            if (mMinimumLogicalFontSize != size) {
558                mMinimumLogicalFontSize = size;
559                mEventHandler.syncSettingsLocked();
560            }
561        }
562    }
563
564    /**
565     * Get the minimum logical font size. The default is 8.
566     * @return A non-negative integer between 1 and 72.
567     */
568    public int getMinimumLogicalFontSize() {
569        synchronized (mContentSettingsLock) {
570            return mMinimumLogicalFontSize;
571        }
572    }
573
574    /**
575     * Set the default font size.
576     * @param size A non-negative integer between 1 and 72.
577     * Any number outside the specified range will be pinned.
578     */
579    public void setDefaultFontSize(int size) {
580        assert mCanModifySettings;
581        synchronized (mContentSettingsLock) {
582            size = clipFontSize(size);
583            if (mDefaultFontSize != size) {
584                mDefaultFontSize = size;
585                mEventHandler.syncSettingsLocked();
586            }
587        }
588    }
589
590    /**
591     * Get the default font size. The default is 16.
592     * @return A non-negative integer between 1 and 72.
593     */
594    public int getDefaultFontSize() {
595        synchronized (mContentSettingsLock) {
596            return mDefaultFontSize;
597        }
598    }
599
600    /**
601     * Set the default fixed font size.
602     * @param size A non-negative integer between 1 and 72.
603     * Any number outside the specified range will be pinned.
604     */
605    public void setDefaultFixedFontSize(int size) {
606        assert mCanModifySettings;
607        synchronized (mContentSettingsLock) {
608            size = clipFontSize(size);
609            if (mDefaultFixedFontSize != size) {
610                mDefaultFixedFontSize = size;
611                mEventHandler.syncSettingsLocked();
612            }
613        }
614    }
615
616    /**
617     * Get the default fixed font size. The default is 16.
618     * @return A non-negative integer between 1 and 72.
619     */
620    public int getDefaultFixedFontSize() {
621        synchronized (mContentSettingsLock) {
622            return mDefaultFixedFontSize;
623        }
624    }
625
626    /**
627     * Tell the WebView to enable JavaScript execution.
628     *
629     * @param flag True if the WebView should execute JavaScript.
630     */
631    public void setJavaScriptEnabled(boolean flag) {
632        assert mCanModifySettings;
633        synchronized (mContentSettingsLock) {
634            if (mJavaScriptEnabled != flag) {
635                mJavaScriptEnabled = flag;
636                mEventHandler.syncSettingsLocked();
637            }
638        }
639    }
640
641    /**
642     * Sets whether JavaScript running in the context of a file scheme URL
643     * should be allowed to access content from any origin. This includes
644     * access to content from other file scheme URLs. See
645     * {@link #setAllowFileAccessFromFileURLs}. To enable the most restrictive,
646     * and therefore secure policy, this setting should be disabled.
647     * <p>
648     * The default value is true for API level
649     * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
650     * and false for API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
651     * and above.
652     *
653     * @param flag whether JavaScript running in the context of a file scheme
654     *             URL should be allowed to access content from any origin
655     */
656    public void setAllowUniversalAccessFromFileURLs(boolean flag) {
657        assert mCanModifySettings;
658        synchronized (mContentSettingsLock) {
659            if (mAllowUniversalAccessFromFileURLs != flag) {
660                mAllowUniversalAccessFromFileURLs = flag;
661                mEventHandler.syncSettingsLocked();
662            }
663        }
664    }
665
666    /**
667     * Sets whether JavaScript running in the context of a file scheme URL
668     * should be allowed to access content from other file scheme URLs. To
669     * enable the most restrictive, and therefore secure policy, this setting
670     * should be disabled. Note that the value of this setting is ignored if
671     * the value of {@link #getAllowUniversalAccessFromFileURLs} is true.
672     * <p>
673     * The default value is true for API level
674     * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
675     * and false for API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
676     * and above.
677     *
678     * @param flag whether JavaScript running in the context of a file scheme
679     *             URL should be allowed to access content from other file
680     *             scheme URLs
681     */
682    public void setAllowFileAccessFromFileURLs(boolean flag) {
683        assert mCanModifySettings;
684        synchronized (mContentSettingsLock) {
685            if (mAllowFileAccessFromFileURLs != flag) {
686                mAllowFileAccessFromFileURLs = flag;
687                mEventHandler.syncSettingsLocked();
688            }
689        }
690    }
691
692    /**
693     * Tell the WebView to load image resources automatically.
694     * Note that setting this flag to false this does not block image loads
695     * from WebCore cache.
696     * @param flag True if the WebView should load images automatically.
697     */
698    public void setLoadsImagesAutomatically(boolean flag) {
699        assert mCanModifySettings;
700        synchronized (mContentSettingsLock) {
701            if (mLoadsImagesAutomatically != flag) {
702                mLoadsImagesAutomatically = flag;
703                mEventHandler.syncSettingsLocked();
704            }
705        }
706    }
707
708    /**
709     * Return true if the WebView will load image resources automatically.
710     * The default is true.
711     * @return True if the WebView loads images automatically.
712     */
713    public boolean getLoadsImagesAutomatically() {
714        synchronized (mContentSettingsLock) {
715            return mLoadsImagesAutomatically;
716        }
717    }
718
719    /**
720     * Sets whether images are enabled for this WebView. Setting this from
721     * false to true will reload the blocked images in place.
722     * Note that unlike {@link #setLoadsImagesAutomatically}, setting this
723     * flag to false this will block image loads from WebCore cache as well.
724     * The default is true.
725     * @param flag whether the WebView should enable images.
726     */
727    public void setImagesEnabled(boolean flag) {
728        assert mCanModifySettings;
729        synchronized (mContentSettingsLock) {
730            if (mImagesEnabled != flag) {
731                mImagesEnabled = flag;
732                mEventHandler.syncSettingsLocked();
733            }
734        }
735    }
736
737    /**
738     * Gets whether images are enabled for this WebView.
739     * @return true if the WebView has images eanbled
740     */
741    public boolean getImagesEnabled() {
742        synchronized (mContentSettingsLock) {
743            return mImagesEnabled;
744        }
745    }
746
747    /**
748     * Return true if JavaScript is enabled. <b>Note: The default is false.</b>
749     *
750     * @return True if JavaScript is enabled.
751     */
752    public boolean getJavaScriptEnabled() {
753        synchronized (mContentSettingsLock) {
754            return mJavaScriptEnabled;
755        }
756    }
757
758    /**
759     * Gets whether JavaScript running in the context of a file scheme URL can
760     * access content from any origin. This includes access to content from
761     * other file scheme URLs.
762     *
763     * @return whether JavaScript running in the context of a file scheme URL
764     *         can access content from any origin
765     * @see #setAllowUniversalAccessFromFileURLs
766     */
767    public boolean getAllowUniversalAccessFromFileURLs() {
768        synchronized (mContentSettingsLock) {
769            return mAllowUniversalAccessFromFileURLs;
770        }
771    }
772
773    /**
774     * Gets whether JavaScript running in the context of a file scheme URL can
775     * access content from other file scheme URLs.
776     *
777     * @return whether JavaScript running in the context of a file scheme URL
778     *         can access content from other file scheme URLs
779     * @see #setAllowFileAccessFromFileURLs
780     */
781    public boolean getAllowFileAccessFromFileURLs() {
782        synchronized (mContentSettingsLock) {
783            return mAllowFileAccessFromFileURLs;
784        }
785    }
786
787    /**
788     * Tell the WebView to enable plugins.
789     * @param flag True if the WebView should load plugins.
790     * @deprecated This method has been deprecated in favor of
791     *             {@link #setPluginState}
792     */
793    @Deprecated
794    public void setPluginsEnabled(boolean flag) {
795        assert mCanModifySettings;
796        setPluginState(flag ? PluginState.ON : PluginState.OFF);
797    }
798
799    /**
800     * Tell the WebView to enable, disable, or have plugins on demand. On
801     * demand mode means that if a plugin exists that can handle the embedded
802     * content, a placeholder icon will be shown instead of the plugin. When
803     * the placeholder is clicked, the plugin will be enabled.
804     * @param state One of the PluginState values.
805     */
806    public void setPluginState(PluginState state) {
807        assert mCanModifySettings;
808        synchronized (mContentSettingsLock) {
809            if (mPluginState != state) {
810                mPluginState = state;
811                mEventHandler.syncSettingsLocked();
812            }
813        }
814    }
815
816    /**
817     * Return true if plugins are enabled.
818     * @return True if plugins are enabled.
819     * @deprecated This method has been replaced by {@link #getPluginState}
820     */
821    @Deprecated
822    public boolean getPluginsEnabled() {
823        synchronized (mContentSettingsLock) {
824            return mPluginState == PluginState.ON;
825        }
826    }
827
828    /**
829     * Return true if plugins are disabled.
830     * @return True if plugins are disabled.
831     * @hide
832     */
833    @CalledByNative
834    private boolean getPluginsDisabled() {
835        synchronized (mContentSettingsLock) {
836            return mPluginState == PluginState.OFF;
837        }
838    }
839
840    /**
841     * Sets if plugins are disabled.
842     * @return True if plugins are disabled.
843     * @hide
844     */
845    @CalledByNative
846    private void setPluginsDisabled(boolean disabled) {
847        synchronized (mContentSettingsLock) {
848            mPluginState = disabled ? PluginState.OFF : PluginState.ON;
849        }
850    }
851
852    /**
853     * Return the current plugin state.
854     * @return A value corresponding to the enum PluginState.
855     */
856    public PluginState getPluginState() {
857        synchronized (mContentSettingsLock) {
858            return mPluginState;
859        }
860    }
861
862
863    /**
864     * Tell javascript to open windows automatically. This applies to the
865     * javascript function window.open().
866     * @param flag True if javascript can open windows automatically.
867     */
868    public void setJavaScriptCanOpenWindowsAutomatically(boolean flag) {
869        assert mCanModifySettings;
870        synchronized (mContentSettingsLock) {
871            if (mJavaScriptCanOpenWindowsAutomatically != flag) {
872                mJavaScriptCanOpenWindowsAutomatically = flag;
873                mEventHandler.syncSettingsLocked();
874            }
875        }
876    }
877
878    /**
879     * Return true if javascript can open windows automatically. The default
880     * is false.
881     * @return True if javascript can open windows automatically during
882     *         window.open().
883     */
884    public boolean getJavaScriptCanOpenWindowsAutomatically() {
885        synchronized (mContentSettingsLock) {
886            return mJavaScriptCanOpenWindowsAutomatically;
887        }
888    }
889
890    /**
891     * Tells the WebView whether it supports multiple windows. True means
892     * that {@link WebChromeClient#onCreateWindow(WebView, boolean,
893     * boolean, Message)} is implemented by the host application.
894     */
895    public void setSupportMultipleWindows(boolean support) {
896        assert mCanModifySettings;
897        synchronized (mContentSettingsLock) {
898            if (mSupportMultipleWindows != support) {
899                mSupportMultipleWindows = support;
900                mEventHandler.syncSettingsLocked();
901            }
902        }
903    }
904
905    /**
906     * Gets whether the WebView is supporting multiple windows.
907     *
908     * @return true if the WebView is supporting multiple windows. This means
909     *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
910     *         boolean, Message)} is implemented by the host application.
911     */
912    public boolean supportMultipleWindows() {
913        synchronized (mContentSettingsLock) {
914            return mSupportMultipleWindows;
915        }
916    }
917
918    /**
919     * Sets whether the DOM storage API is enabled. The default value is false.
920     *
921     * @param flag true if the ContentView should use the DOM storage API
922     */
923    public void setDomStorageEnabled(boolean flag) {
924        assert mCanModifySettings;
925        synchronized (mContentSettingsLock) {
926            if (mDomStorageEnabled != flag) {
927                mDomStorageEnabled = flag;
928                mEventHandler.syncSettingsLocked();
929            }
930        }
931    }
932
933    /**
934     * Gets whether the DOM Storage APIs are enabled.
935     *
936     * @return true if the DOM Storage APIs are enabled
937     * @see #setDomStorageEnabled
938     */
939    public boolean getDomStorageEnabled() {
940       synchronized (mContentSettingsLock) {
941           return mDomStorageEnabled;
942       }
943    }
944
945    /**
946     * Set the default text encoding name to use when decoding html pages.
947     * @param encoding The text encoding name.
948     */
949    public void setDefaultTextEncodingName(String encoding) {
950        assert mCanModifySettings;
951        synchronized (mContentSettingsLock) {
952            if (!mDefaultTextEncoding.equals(encoding)) {
953                mDefaultTextEncoding = encoding;
954                mEventHandler.syncSettingsLocked();
955            }
956        }
957    }
958
959    /**
960     * Get the default text encoding name. The default is "Latin-1".
961     * @return The default text encoding name as a string.
962     */
963    public String getDefaultTextEncodingName() {
964        synchronized (mContentSettingsLock) {
965            return mDefaultTextEncoding;
966        }
967    }
968
969    private int clipFontSize(int size) {
970        if (size < MINIMUM_FONT_SIZE) {
971            return MINIMUM_FONT_SIZE;
972        } else if (size > MAXIMUM_FONT_SIZE) {
973            return MAXIMUM_FONT_SIZE;
974        }
975        return size;
976    }
977
978    /**
979     * Synchronize java side and native side settings. When ContentView
980     * is running in PERSONALITY_VIEW mode, this needs to be done after
981     * any java side setting is changed to sync them to native. In
982     * PERSONALITY_CHROME mode, this needs to be called whenever native
983     * settings are changed to sync them to java.
984     */
985    void syncSettings() {
986        synchronized (mContentSettingsLock) {
987            mEventHandler.syncSettingsLocked();
988        }
989    }
990
991    void syncToNativeOnUiThread() {
992        if (mNativeContentSettings != 0) nativeSyncToNative(mNativeContentSettings);
993    }
994
995    void syncFromNativeOnUiThread() {
996        if (mNativeContentSettings != 0) nativeSyncFromNative(mNativeContentSettings);
997    }
998
999    // Initialize the ContentSettings native side.
1000    private native int nativeInit(int contentViewPtr, boolean isMasterMode);
1001
1002    private static native String nativeGetDefaultUserAgent();
1003
1004    // Synchronize Java settings from native settings.
1005    private native void nativeSyncFromNative(int nativeContentSettings);
1006
1007    // Synchronize native settings from Java settings.
1008    private native void nativeSyncToNative(int nativeContentSettings);
1009}
1010