587ca48d870de2d12ece8c3870a4bacf8da70d15
[platform/framework/web/crosswalk.git] / src / android_webview / java / src / org / chromium / android_webview / AwSettings.java
1 // Copyright 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
5 package org.chromium.android_webview;
6
7 import android.content.Context;
8 import android.content.pm.PackageManager;
9 import android.os.Handler;
10 import android.os.Message;
11 import android.os.Process;
12 import android.provider.Settings;
13 import android.util.Log;
14 import android.webkit.WebSettings;
15 import android.webkit.WebSettings.PluginState;
16
17 import com.google.common.annotations.VisibleForTesting;
18
19 import org.chromium.base.CalledByNative;
20 import org.chromium.base.JNINamespace;
21 import org.chromium.base.ThreadUtils;
22
23 /**
24  * Stores Android WebView specific settings that does not need to be synced to WebKit.
25  * Use {@link org.chromium.content.browser.ContentSettings} for WebKit settings.
26  *
27  * Methods in this class can be called from any thread, including threads created by
28  * the client of WebView.
29  */
30 @JNINamespace("android_webview")
31 public class AwSettings {
32     // This enum corresponds to WebSettings.LayoutAlgorithm. We use our own to be
33     // able to extend it.
34     public enum LayoutAlgorithm {
35         NORMAL,
36         SINGLE_COLUMN,
37         NARROW_COLUMNS,
38         TEXT_AUTOSIZING,
39     }
40
41     // These constants must be kept in sync with the Android framework, defined in WebSettimgs.
42     @VisibleForTesting
43     public static final int MIXED_CONTENT_ALWAYS_ALLOW = 0;
44     @VisibleForTesting
45     public static final int MIXED_CONTENT_NEVER_ALLOW = 1;
46     @VisibleForTesting
47     public static final int MIXED_CONTENT_COMPATIBILITY_MODE = 2;
48
49     private static final String TAG = "AwSettings";
50
51     // This class must be created on the UI thread. Afterwards, it can be
52     // used from any thread. Internally, the class uses a message queue
53     // to call native code on the UI thread only.
54
55     // Values passed in on construction.
56     private final boolean mHasInternetPermission;
57
58     private ZoomSupportChangeListener mZoomChangeListener;
59     private double mDIPScale = 1.0;
60
61     // Lock to protect all settings.
62     private final Object mAwSettingsLock = new Object();
63
64     private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
65     private int mTextSizePercent = 100;
66     private String mStandardFontFamily = "sans-serif";
67     private String mFixedFontFamily = "monospace";
68     private String mSansSerifFontFamily = "sans-serif";
69     private String mSerifFontFamily = "serif";
70     private String mCursiveFontFamily = "cursive";
71     private String mFantasyFontFamily = "fantasy";
72     private String mDefaultTextEncoding;
73     private String mUserAgent;
74     private int mMinimumFontSize = 8;
75     private int mMinimumLogicalFontSize = 8;
76     private int mDefaultFontSize = 16;
77     private int mDefaultFixedFontSize = 13;
78     private boolean mLoadsImagesAutomatically = true;
79     private boolean mImagesEnabled = true;
80     private boolean mJavaScriptEnabled = false;
81     private boolean mAllowUniversalAccessFromFileURLs = false;
82     private boolean mAllowFileAccessFromFileURLs = false;
83     private boolean mJavaScriptCanOpenWindowsAutomatically = false;
84     private boolean mSupportMultipleWindows = false;
85     private PluginState mPluginState = PluginState.OFF;
86     private boolean mAppCacheEnabled = false;
87     private boolean mDomStorageEnabled = false;
88     private boolean mDatabaseEnabled = false;
89     private boolean mUseWideViewport = false;
90     private boolean mLoadWithOverviewMode = false;
91     private boolean mMediaPlaybackRequiresUserGesture = true;
92     private String mDefaultVideoPosterURL;
93     private float mInitialPageScalePercent = 0;
94     private boolean mSpatialNavigationEnabled;  // Default depends on device features.
95     private boolean mEnableSupportedHardwareAcceleratedFeatures = false;
96     private int mMixedContentMode = MIXED_CONTENT_NEVER_ALLOW;
97     private boolean mVideoOverlayForEmbeddedVideoEnabled = false;
98
99     // Although this bit is stored on AwSettings it is actually controlled via the CookieManager.
100     private boolean mAcceptThirdPartyCookies;
101
102     private final boolean mSupportLegacyQuirks;
103
104     private final boolean mPasswordEchoEnabled;
105
106     // Not accessed by the native side.
107     private boolean mBlockNetworkLoads;  // Default depends on permission of embedding APK.
108     private boolean mAllowContentUrlAccess = true;
109     private boolean mAllowFileUrlAccess = true;
110     private int mCacheMode = WebSettings.LOAD_DEFAULT;
111     private boolean mShouldFocusFirstNode = true;
112     private boolean mGeolocationEnabled = true;
113     private boolean mAutoCompleteEnabled = true;
114     private boolean mSupportZoom = true;
115     private boolean mBuiltInZoomControls = false;
116     private boolean mDisplayZoomControls = true;
117
118     static class LazyDefaultUserAgent{
119         // Lazy Holder pattern
120         private static final String sInstance = nativeGetDefaultUserAgent();
121     }
122
123     // Protects access to settings global fields.
124     private static final Object sGlobalContentSettingsLock = new Object();
125     // For compatibility with the legacy WebView, we can only enable AppCache when the path is
126     // provided. However, we don't use the path, so we just check if we have received it from the
127     // client.
128     private static boolean sAppCachePathIsSet = false;
129
130     // The native side of this object. It's lifetime is bounded by the WebContent it is attached to.
131     private long mNativeAwSettings = 0;
132
133     // Custom handler that queues messages to call native code on the UI thread.
134     private final EventHandler mEventHandler;
135
136     private static final int MINIMUM_FONT_SIZE = 1;
137     private static final int MAXIMUM_FONT_SIZE = 72;
138
139     // Class to handle messages to be processed on the UI thread.
140     private class EventHandler {
141         // Message id for running a Runnable with mAwSettingsLock held.
142         private static final int RUN_RUNNABLE_BLOCKING = 0;
143         // Actual UI thread handler
144         private Handler mHandler;
145         // Synchronization flag.
146         private boolean mSynchronizationPending = false;
147
148         EventHandler() {
149         }
150
151         void bindUiThread() {
152             if (mHandler != null) return;
153             mHandler = new Handler(ThreadUtils.getUiThreadLooper()) {
154                 @Override
155                 public void handleMessage(Message msg) {
156                     switch (msg.what) {
157                         case RUN_RUNNABLE_BLOCKING:
158                             synchronized (mAwSettingsLock) {
159                                 if (mNativeAwSettings != 0) {
160                                     ((Runnable)msg.obj).run();
161                                 }
162                                 mSynchronizationPending = false;
163                                 mAwSettingsLock.notifyAll();
164                             }
165                             break;
166                     }
167                 }
168             };
169         }
170
171         void runOnUiThreadBlockingAndLocked(Runnable r) {
172             assert Thread.holdsLock(mAwSettingsLock);
173             if (mHandler == null) return;
174             if (ThreadUtils.runningOnUiThread()) {
175                 r.run();
176             } else {
177                 assert !mSynchronizationPending;
178                 mSynchronizationPending = true;
179                 mHandler.sendMessage(Message.obtain(null, RUN_RUNNABLE_BLOCKING, r));
180                 try {
181                     while (mSynchronizationPending) {
182                         mAwSettingsLock.wait();
183                     }
184                 } catch (InterruptedException e) {
185                     Log.e(TAG, "Interrupted waiting a Runnable to complete", e);
186                     mSynchronizationPending = false;
187                 }
188             }
189         }
190
191         void maybePostOnUiThread(Runnable r) {
192             if (mHandler != null) {
193                 mHandler.post(r);
194             }
195         }
196
197         void updateWebkitPreferencesLocked() {
198             runOnUiThreadBlockingAndLocked(new Runnable() {
199                 @Override
200                 public void run() {
201                     updateWebkitPreferencesOnUiThreadLocked();
202                 }
203             });
204         }
205     }
206
207     interface ZoomSupportChangeListener {
208         public void onGestureZoomSupportChanged(
209                 boolean supportsDoubleTapZoom, boolean supportsMultiTouchZoom);
210     }
211
212     public AwSettings(Context context,
213             boolean isAccessFromFileURLsGrantedByDefault,
214             boolean supportsLegacyQuirks) {
215        boolean hasInternetPermission = context.checkPermission(
216                     android.Manifest.permission.INTERNET,
217                     Process.myPid(),
218                     Process.myUid()) == PackageManager.PERMISSION_GRANTED;
219         synchronized (mAwSettingsLock) {
220             mHasInternetPermission = hasInternetPermission;
221             mBlockNetworkLoads = !hasInternetPermission;
222             mEventHandler = new EventHandler();
223             if (isAccessFromFileURLsGrantedByDefault) {
224                 mAllowUniversalAccessFromFileURLs = true;
225                 mAllowFileAccessFromFileURLs = true;
226             }
227
228             mDefaultTextEncoding = AwResource.getDefaultTextEncoding();
229             mUserAgent = LazyDefaultUserAgent.sInstance;
230
231             // Best-guess a sensible initial value based on the features supported on the device.
232             mSpatialNavigationEnabled = !context.getPackageManager().hasSystemFeature(
233                     PackageManager.FEATURE_TOUCHSCREEN);
234
235             // Respect the system setting for password echoing.
236             mPasswordEchoEnabled = Settings.System.getInt(context.getContentResolver(),
237                     Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
238
239             // By default, scale the text size by the system font scale factor. Embedders
240             // may override this by invoking setTextZoom().
241             mTextSizePercent *= context.getResources().getConfiguration().fontScale;
242
243             mSupportLegacyQuirks = supportsLegacyQuirks;
244         }
245         // Defer initializing the native side until a native WebContents instance is set.
246     }
247
248     @CalledByNative
249     private void nativeAwSettingsGone(long nativeAwSettings) {
250         assert mNativeAwSettings != 0 && mNativeAwSettings == nativeAwSettings;
251         mNativeAwSettings = 0;
252     }
253
254     @CalledByNative
255     private double getDIPScaleLocked() {
256         assert Thread.holdsLock(mAwSettingsLock);
257         return mDIPScale;
258     }
259
260     void setDIPScale(double dipScale) {
261         synchronized (mAwSettingsLock) {
262             mDIPScale = dipScale;
263             // TODO(joth): This should also be synced over to native side, but right now
264             // the setDIPScale call is always followed by a setWebContents() which covers this.
265         }
266     }
267
268     void setZoomListener(ZoomSupportChangeListener zoomChangeListener) {
269         synchronized (mAwSettingsLock) {
270             mZoomChangeListener = zoomChangeListener;
271         }
272     }
273
274     void setWebContents(long nativeWebContents) {
275         synchronized (mAwSettingsLock) {
276             if (mNativeAwSettings != 0) {
277                 nativeDestroy(mNativeAwSettings);
278                 assert mNativeAwSettings == 0;  // nativeAwSettingsGone should have been called.
279             }
280             if (nativeWebContents != 0) {
281                 mEventHandler.bindUiThread();
282                 mNativeAwSettings = nativeInit(nativeWebContents);
283                 updateEverythingLocked();
284             }
285         }
286     }
287
288     private void updateEverythingLocked() {
289         assert Thread.holdsLock(mAwSettingsLock);
290         assert mNativeAwSettings != 0;
291         nativeUpdateEverythingLocked(mNativeAwSettings);
292         onGestureZoomSupportChanged(
293                 supportsDoubleTapZoomLocked(), supportsMultiTouchZoomLocked());
294     }
295
296     /**
297      * See {@link android.webkit.WebSettings#setBlockNetworkLoads}.
298      */
299     public void setBlockNetworkLoads(boolean flag) {
300         synchronized (mAwSettingsLock) {
301             if (!flag && !mHasInternetPermission) {
302                 throw new SecurityException("Permission denied - " +
303                         "application missing INTERNET permission");
304             }
305             mBlockNetworkLoads = flag;
306         }
307     }
308
309     /**
310      * See {@link android.webkit.WebSettings#getBlockNetworkLoads}.
311      */
312     public boolean getBlockNetworkLoads() {
313         synchronized (mAwSettingsLock) {
314             return mBlockNetworkLoads;
315         }
316     }
317
318     /**
319      * Enable/disable third party cookies for an AwContents
320      * @param accept true if we should accept third party cookies
321      */
322     public void setAcceptThirdPartyCookies(boolean accept) {
323         synchronized (mAwSettingsLock) {
324             if (mAcceptThirdPartyCookies != accept) {
325                 mAcceptThirdPartyCookies = accept;
326             }
327         }
328     }
329
330     /**
331      * Return whether third party cookies are enabled for an AwContents
332      * @return true if accept third party cookies
333      */
334     public boolean getAcceptThirdPartyCookies() {
335         synchronized (mAwSettingsLock) {
336             return mAcceptThirdPartyCookies;
337         }
338     }
339
340     /**
341      * See {@link android.webkit.WebSettings#setAllowFileAccess}.
342      */
343     public void setAllowFileAccess(boolean allow) {
344         synchronized (mAwSettingsLock) {
345             if (mAllowFileUrlAccess != allow) {
346                 mAllowFileUrlAccess = allow;
347             }
348         }
349     }
350
351     /**
352      * See {@link android.webkit.WebSettings#getAllowFileAccess}.
353      */
354     public boolean getAllowFileAccess() {
355         synchronized (mAwSettingsLock) {
356             return mAllowFileUrlAccess;
357         }
358     }
359
360     /**
361      * See {@link android.webkit.WebSettings#setAllowContentAccess}.
362      */
363     public void setAllowContentAccess(boolean allow) {
364         synchronized (mAwSettingsLock) {
365             if (mAllowContentUrlAccess != allow) {
366                 mAllowContentUrlAccess = allow;
367             }
368         }
369     }
370
371     /**
372      * See {@link android.webkit.WebSettings#getAllowContentAccess}.
373      */
374     public boolean getAllowContentAccess() {
375         synchronized (mAwSettingsLock) {
376             return mAllowContentUrlAccess;
377         }
378     }
379
380     /**
381      * See {@link android.webkit.WebSettings#setCacheMode}.
382      */
383     public void setCacheMode(int mode) {
384         synchronized (mAwSettingsLock) {
385             if (mCacheMode != mode) {
386                 mCacheMode = mode;
387             }
388         }
389     }
390
391     /**
392      * See {@link android.webkit.WebSettings#getCacheMode}.
393      */
394     public int getCacheMode() {
395         synchronized (mAwSettingsLock) {
396             return mCacheMode;
397         }
398     }
399
400     /**
401      * See {@link android.webkit.WebSettings#setNeedInitialFocus}.
402      */
403     public void setShouldFocusFirstNode(boolean flag) {
404         synchronized (mAwSettingsLock) {
405             mShouldFocusFirstNode = flag;
406         }
407     }
408
409     /**
410      * See {@link android.webkit.WebView#setInitialScale}.
411      */
412     public void setInitialPageScale(final float scaleInPercent) {
413         synchronized (mAwSettingsLock) {
414             if (mInitialPageScalePercent != scaleInPercent) {
415                 mInitialPageScalePercent = scaleInPercent;
416                 mEventHandler.runOnUiThreadBlockingAndLocked(new Runnable() {
417                     @Override
418                     public void run() {
419                         if (mNativeAwSettings != 0) {
420                             nativeUpdateInitialPageScaleLocked(mNativeAwSettings);
421                         }
422                     }
423                 });
424             }
425         }
426     }
427
428     @CalledByNative
429     private float getInitialPageScalePercentLocked() {
430         assert Thread.holdsLock(mAwSettingsLock);
431         return mInitialPageScalePercent;
432     }
433
434     void setSpatialNavigationEnabled(boolean enable) {
435         synchronized (mAwSettingsLock) {
436             if (mSpatialNavigationEnabled != enable) {
437                 mSpatialNavigationEnabled = enable;
438                 mEventHandler.updateWebkitPreferencesLocked();
439             }
440         }
441     }
442
443     @CalledByNative
444     private boolean getSpatialNavigationLocked() {
445         assert Thread.holdsLock(mAwSettingsLock);
446         return mSpatialNavigationEnabled;
447     }
448
449     void setEnableSupportedHardwareAcceleratedFeatures(boolean enable) {
450         synchronized (mAwSettingsLock) {
451             if (mEnableSupportedHardwareAcceleratedFeatures != enable) {
452                 mEnableSupportedHardwareAcceleratedFeatures = enable;
453                 mEventHandler.updateWebkitPreferencesLocked();
454             }
455         }
456     }
457
458     @CalledByNative
459     private boolean getEnableSupportedHardwareAcceleratedFeaturesLocked() {
460         assert Thread.holdsLock(mAwSettingsLock);
461         return mEnableSupportedHardwareAcceleratedFeatures;
462     }
463
464     /**
465      * See {@link android.webkit.WebSettings#setNeedInitialFocus}.
466      */
467     public boolean shouldFocusFirstNode() {
468         synchronized (mAwSettingsLock) {
469             return mShouldFocusFirstNode;
470         }
471     }
472
473     /**
474      * See {@link android.webkit.WebSettings#setGeolocationEnabled}.
475      */
476     public void setGeolocationEnabled(boolean flag) {
477         synchronized (mAwSettingsLock) {
478             if (mGeolocationEnabled != flag) {
479                 mGeolocationEnabled = flag;
480             }
481         }
482     }
483
484     /**
485      * @return Returns if geolocation is currently enabled.
486      */
487     boolean getGeolocationEnabled() {
488         synchronized (mAwSettingsLock) {
489             return mGeolocationEnabled;
490         }
491     }
492
493     /**
494      * See {@link android.webkit.WebSettings#setSaveFormData}.
495      */
496     public void setSaveFormData(final boolean enable) {
497         synchronized (mAwSettingsLock) {
498             if (mAutoCompleteEnabled != enable) {
499                 mAutoCompleteEnabled = enable;
500                 mEventHandler.runOnUiThreadBlockingAndLocked(new Runnable() {
501                     @Override
502                     public void run() {
503                         if (mNativeAwSettings != 0) {
504                             nativeUpdateFormDataPreferencesLocked(mNativeAwSettings);
505                         }
506                     }
507                 });
508             }
509         }
510     }
511
512     /**
513      * See {@link android.webkit.WebSettings#getSaveFormData}.
514      */
515     public boolean getSaveFormData() {
516         synchronized (mAwSettingsLock) {
517             return getSaveFormDataLocked();
518         }
519     }
520
521     @CalledByNative
522     private boolean getSaveFormDataLocked() {
523         assert Thread.holdsLock(mAwSettingsLock);
524         return mAutoCompleteEnabled;
525     }
526
527     /**
528      * @returns the default User-Agent used by each ContentViewCore instance, i.e. unless
529      * overridden by {@link #setUserAgentString()}
530      */
531     public static String getDefaultUserAgent() {
532         return LazyDefaultUserAgent.sInstance;
533     }
534
535     /**
536      * See {@link android.webkit.WebSettings#setUserAgentString}.
537      */
538     public void setUserAgentString(String ua) {
539         synchronized (mAwSettingsLock) {
540             final String oldUserAgent = mUserAgent;
541             if (ua == null || ua.length() == 0) {
542                 mUserAgent = LazyDefaultUserAgent.sInstance;
543             } else {
544                 mUserAgent = ua;
545             }
546             if (!oldUserAgent.equals(mUserAgent)) {
547                 mEventHandler.runOnUiThreadBlockingAndLocked(new Runnable() {
548                     @Override
549                     public void run() {
550                         if (mNativeAwSettings != 0) {
551                             nativeUpdateUserAgentLocked(mNativeAwSettings);
552                         }
553                     }
554                 });
555             }
556         }
557     }
558
559     /**
560      * See {@link android.webkit.WebSettings#getUserAgentString}.
561      */
562     public String getUserAgentString() {
563         synchronized (mAwSettingsLock) {
564             return getUserAgentLocked();
565         }
566     }
567
568     @CalledByNative
569     private String getUserAgentLocked() {
570         assert Thread.holdsLock(mAwSettingsLock);
571         return mUserAgent;
572     }
573
574     /**
575      * See {@link android.webkit.WebSettings#setLoadWithOverviewMode}.
576      */
577     public void setLoadWithOverviewMode(boolean overview) {
578         synchronized (mAwSettingsLock) {
579             if (mLoadWithOverviewMode != overview) {
580                 mLoadWithOverviewMode = overview;
581                 mEventHandler.runOnUiThreadBlockingAndLocked(new Runnable() {
582                     @Override
583                     public void run() {
584                         if (mNativeAwSettings != 0) {
585                             updateWebkitPreferencesOnUiThreadLocked();
586                             nativeResetScrollAndScaleState(mNativeAwSettings);
587                         }
588                     }
589                 });
590             }
591         }
592     }
593
594     /**
595      * See {@link android.webkit.WebSettings#getLoadWithOverviewMode}.
596      */
597     public boolean getLoadWithOverviewMode() {
598         synchronized (mAwSettingsLock) {
599             return getLoadWithOverviewModeLocked();
600         }
601     }
602
603     @CalledByNative
604     private boolean getLoadWithOverviewModeLocked() {
605         assert Thread.holdsLock(mAwSettingsLock);
606         return mLoadWithOverviewMode;
607     }
608
609     /**
610      * See {@link android.webkit.WebSettings#setTextZoom}.
611      */
612     public void setTextZoom(final int textZoom) {
613         synchronized (mAwSettingsLock) {
614             if (mTextSizePercent != textZoom) {
615                 mTextSizePercent = textZoom;
616                 mEventHandler.updateWebkitPreferencesLocked();
617             }
618         }
619     }
620
621     /**
622      * See {@link android.webkit.WebSettings#getTextZoom}.
623      */
624     public int getTextZoom() {
625         synchronized (mAwSettingsLock) {
626             return getTextSizePercentLocked();
627         }
628     }
629
630     @CalledByNative
631     private int getTextSizePercentLocked() {
632         assert Thread.holdsLock(mAwSettingsLock);
633         return mTextSizePercent;
634     }
635
636     /**
637      * See {@link android.webkit.WebSettings#setStandardFontFamily}.
638      */
639     public void setStandardFontFamily(String font) {
640         synchronized (mAwSettingsLock) {
641             if (font != null && !mStandardFontFamily.equals(font)) {
642                 mStandardFontFamily = font;
643                 mEventHandler.updateWebkitPreferencesLocked();
644             }
645         }
646     }
647
648     /**
649      * See {@link android.webkit.WebSettings#getStandardFontFamily}.
650      */
651     public String getStandardFontFamily() {
652         synchronized (mAwSettingsLock) {
653             return getStandardFontFamilyLocked();
654         }
655     }
656
657     @CalledByNative
658     private String getStandardFontFamilyLocked() {
659         assert Thread.holdsLock(mAwSettingsLock);
660         return mStandardFontFamily;
661     }
662
663     /**
664      * See {@link android.webkit.WebSettings#setFixedFontFamily}.
665      */
666     public void setFixedFontFamily(String font) {
667         synchronized (mAwSettingsLock) {
668             if (font != null && !mFixedFontFamily.equals(font)) {
669                 mFixedFontFamily = font;
670                 mEventHandler.updateWebkitPreferencesLocked();
671             }
672         }
673     }
674
675     /**
676      * See {@link android.webkit.WebSettings#getFixedFontFamily}.
677      */
678     public String getFixedFontFamily() {
679         synchronized (mAwSettingsLock) {
680             return getFixedFontFamilyLocked();
681         }
682     }
683
684     @CalledByNative
685     private String getFixedFontFamilyLocked() {
686         assert Thread.holdsLock(mAwSettingsLock);
687         return mFixedFontFamily;
688     }
689
690     /**
691      * See {@link android.webkit.WebSettings#setSansSerifFontFamily}.
692      */
693     public void setSansSerifFontFamily(String font) {
694         synchronized (mAwSettingsLock) {
695             if (font != null && !mSansSerifFontFamily.equals(font)) {
696                 mSansSerifFontFamily = font;
697                 mEventHandler.updateWebkitPreferencesLocked();
698             }
699         }
700     }
701
702     /**
703      * See {@link android.webkit.WebSettings#getSansSerifFontFamily}.
704      */
705     public String getSansSerifFontFamily() {
706         synchronized (mAwSettingsLock) {
707             return getSansSerifFontFamilyLocked();
708         }
709     }
710
711     @CalledByNative
712     private String getSansSerifFontFamilyLocked() {
713         assert Thread.holdsLock(mAwSettingsLock);
714         return mSansSerifFontFamily;
715     }
716
717     /**
718      * See {@link android.webkit.WebSettings#setSerifFontFamily}.
719      */
720     public void setSerifFontFamily(String font) {
721         synchronized (mAwSettingsLock) {
722             if (font != null && !mSerifFontFamily.equals(font)) {
723                 mSerifFontFamily = font;
724                 mEventHandler.updateWebkitPreferencesLocked();
725             }
726         }
727     }
728
729     /**
730      * See {@link android.webkit.WebSettings#getSerifFontFamily}.
731      */
732     public String getSerifFontFamily() {
733         synchronized (mAwSettingsLock) {
734             return getSerifFontFamilyLocked();
735         }
736     }
737
738     @CalledByNative
739     private String getSerifFontFamilyLocked() {
740         assert Thread.holdsLock(mAwSettingsLock);
741         return mSerifFontFamily;
742     }
743
744     /**
745      * See {@link android.webkit.WebSettings#setCursiveFontFamily}.
746      */
747     public void setCursiveFontFamily(String font) {
748         synchronized (mAwSettingsLock) {
749             if (font != null && !mCursiveFontFamily.equals(font)) {
750                 mCursiveFontFamily = font;
751                 mEventHandler.updateWebkitPreferencesLocked();
752             }
753         }
754     }
755
756     /**
757      * See {@link android.webkit.WebSettings#getCursiveFontFamily}.
758      */
759     public String getCursiveFontFamily() {
760         synchronized (mAwSettingsLock) {
761             return getCursiveFontFamilyLocked();
762         }
763     }
764
765     @CalledByNative
766     private String getCursiveFontFamilyLocked() {
767         assert Thread.holdsLock(mAwSettingsLock);
768         return mCursiveFontFamily;
769     }
770
771     /**
772      * See {@link android.webkit.WebSettings#setFantasyFontFamily}.
773      */
774     public void setFantasyFontFamily(String font) {
775         synchronized (mAwSettingsLock) {
776             if (font != null && !mFantasyFontFamily.equals(font)) {
777                 mFantasyFontFamily = font;
778                 mEventHandler.updateWebkitPreferencesLocked();
779             }
780         }
781     }
782
783     /**
784      * See {@link android.webkit.WebSettings#getFantasyFontFamily}.
785      */
786     public String getFantasyFontFamily() {
787         synchronized (mAwSettingsLock) {
788             return getFantasyFontFamilyLocked();
789         }
790     }
791
792     @CalledByNative
793     private String getFantasyFontFamilyLocked() {
794         assert Thread.holdsLock(mAwSettingsLock);
795         return mFantasyFontFamily;
796     }
797
798     /**
799      * See {@link android.webkit.WebSettings#setMinimumFontSize}.
800      */
801     public void setMinimumFontSize(int size) {
802         synchronized (mAwSettingsLock) {
803             size = clipFontSize(size);
804             if (mMinimumFontSize != size) {
805                 mMinimumFontSize = size;
806                 mEventHandler.updateWebkitPreferencesLocked();
807             }
808         }
809     }
810
811     /**
812      * See {@link android.webkit.WebSettings#getMinimumFontSize}.
813      */
814     public int getMinimumFontSize() {
815         synchronized (mAwSettingsLock) {
816             return getMinimumFontSizeLocked();
817         }
818     }
819
820     @CalledByNative
821     private int getMinimumFontSizeLocked() {
822         assert Thread.holdsLock(mAwSettingsLock);
823         return mMinimumFontSize;
824     }
825
826     /**
827      * See {@link android.webkit.WebSettings#setMinimumLogicalFontSize}.
828      */
829     public void setMinimumLogicalFontSize(int size) {
830         synchronized (mAwSettingsLock) {
831             size = clipFontSize(size);
832             if (mMinimumLogicalFontSize != size) {
833                 mMinimumLogicalFontSize = size;
834                 mEventHandler.updateWebkitPreferencesLocked();
835             }
836         }
837     }
838
839     /**
840      * See {@link android.webkit.WebSettings#getMinimumLogicalFontSize}.
841      */
842     public int getMinimumLogicalFontSize() {
843         synchronized (mAwSettingsLock) {
844             return getMinimumLogicalFontSizeLocked();
845         }
846     }
847
848     @CalledByNative
849     private int getMinimumLogicalFontSizeLocked() {
850         assert Thread.holdsLock(mAwSettingsLock);
851         return mMinimumLogicalFontSize;
852     }
853
854     /**
855      * See {@link android.webkit.WebSettings#setDefaultFontSize}.
856      */
857     public void setDefaultFontSize(int size) {
858         synchronized (mAwSettingsLock) {
859             size = clipFontSize(size);
860             if (mDefaultFontSize != size) {
861                 mDefaultFontSize = size;
862                 mEventHandler.updateWebkitPreferencesLocked();
863             }
864         }
865     }
866
867     /**
868      * See {@link android.webkit.WebSettings#getDefaultFontSize}.
869      */
870     public int getDefaultFontSize() {
871         synchronized (mAwSettingsLock) {
872             return getDefaultFontSizeLocked();
873         }
874     }
875
876     @CalledByNative
877     private int getDefaultFontSizeLocked() {
878         assert Thread.holdsLock(mAwSettingsLock);
879         return mDefaultFontSize;
880     }
881
882     /**
883      * See {@link android.webkit.WebSettings#setDefaultFixedFontSize}.
884      */
885     public void setDefaultFixedFontSize(int size) {
886         synchronized (mAwSettingsLock) {
887             size = clipFontSize(size);
888             if (mDefaultFixedFontSize != size) {
889                 mDefaultFixedFontSize = size;
890                 mEventHandler.updateWebkitPreferencesLocked();
891             }
892         }
893     }
894
895     /**
896      * See {@link android.webkit.WebSettings#getDefaultFixedFontSize}.
897      */
898     public int getDefaultFixedFontSize() {
899         synchronized (mAwSettingsLock) {
900             return getDefaultFixedFontSizeLocked();
901         }
902     }
903
904     @CalledByNative
905     private int getDefaultFixedFontSizeLocked() {
906         assert Thread.holdsLock(mAwSettingsLock);
907         return mDefaultFixedFontSize;
908     }
909
910     /**
911      * See {@link android.webkit.WebSettings#setJavaScriptEnabled}.
912      */
913     public void setJavaScriptEnabled(boolean flag) {
914         synchronized (mAwSettingsLock) {
915             if (mJavaScriptEnabled != flag) {
916                 mJavaScriptEnabled = flag;
917                 mEventHandler.updateWebkitPreferencesLocked();
918             }
919         }
920     }
921
922     /**
923      * See {@link android.webkit.WebSettings#setAllowUniversalAccessFromFileURLs}.
924      */
925     public void setAllowUniversalAccessFromFileURLs(boolean flag) {
926         synchronized (mAwSettingsLock) {
927             if (mAllowUniversalAccessFromFileURLs != flag) {
928                 mAllowUniversalAccessFromFileURLs = flag;
929                 mEventHandler.updateWebkitPreferencesLocked();
930             }
931         }
932     }
933
934     /**
935      * See {@link android.webkit.WebSettings#setAllowFileAccessFromFileURLs}.
936      */
937     public void setAllowFileAccessFromFileURLs(boolean flag) {
938         synchronized (mAwSettingsLock) {
939             if (mAllowFileAccessFromFileURLs != flag) {
940                 mAllowFileAccessFromFileURLs = flag;
941                 mEventHandler.updateWebkitPreferencesLocked();
942             }
943         }
944     }
945
946     /**
947      * See {@link android.webkit.WebSettings#setLoadsImagesAutomatically}.
948      */
949     public void setLoadsImagesAutomatically(boolean flag) {
950         synchronized (mAwSettingsLock) {
951             if (mLoadsImagesAutomatically != flag) {
952                 mLoadsImagesAutomatically = flag;
953                 mEventHandler.updateWebkitPreferencesLocked();
954             }
955         }
956     }
957
958     /**
959      * See {@link android.webkit.WebSettings#getLoadsImagesAutomatically}.
960      */
961     public boolean getLoadsImagesAutomatically() {
962         synchronized (mAwSettingsLock) {
963             return getLoadsImagesAutomaticallyLocked();
964         }
965     }
966
967     @CalledByNative
968     private boolean getLoadsImagesAutomaticallyLocked() {
969         assert Thread.holdsLock(mAwSettingsLock);
970         return mLoadsImagesAutomatically;
971     }
972
973     /**
974      * See {@link android.webkit.WebSettings#setImagesEnabled}.
975      */
976     public void setImagesEnabled(boolean flag) {
977         synchronized (mAwSettingsLock) {
978             if (mImagesEnabled != flag) {
979                 mImagesEnabled = flag;
980                 mEventHandler.updateWebkitPreferencesLocked();
981             }
982         }
983     }
984
985     /**
986      * See {@link android.webkit.WebSettings#getImagesEnabled}.
987      */
988     public boolean getImagesEnabled() {
989         synchronized (mAwSettingsLock) {
990             return mImagesEnabled;
991         }
992     }
993
994     @CalledByNative
995     private boolean getImagesEnabledLocked() {
996         assert Thread.holdsLock(mAwSettingsLock);
997         return mImagesEnabled;
998     }
999
1000     /**
1001      * See {@link android.webkit.WebSettings#getJavaScriptEnabled}.
1002      */
1003     public boolean getJavaScriptEnabled() {
1004         synchronized (mAwSettingsLock) {
1005             return mJavaScriptEnabled;
1006         }
1007     }
1008
1009     @CalledByNative
1010     private boolean getJavaScriptEnabledLocked() {
1011         assert Thread.holdsLock(mAwSettingsLock);
1012         return mJavaScriptEnabled;
1013     }
1014
1015     /**
1016      * See {@link android.webkit.WebSettings#getAllowUniversalAccessFromFileURLs}.
1017      */
1018     public boolean getAllowUniversalAccessFromFileURLs() {
1019         synchronized (mAwSettingsLock) {
1020             return getAllowUniversalAccessFromFileURLsLocked();
1021         }
1022     }
1023
1024     @CalledByNative
1025     private boolean getAllowUniversalAccessFromFileURLsLocked() {
1026         assert Thread.holdsLock(mAwSettingsLock);
1027         return mAllowUniversalAccessFromFileURLs;
1028     }
1029
1030     /**
1031      * See {@link android.webkit.WebSettings#getAllowFileAccessFromFileURLs}.
1032      */
1033     public boolean getAllowFileAccessFromFileURLs() {
1034         synchronized (mAwSettingsLock) {
1035             return getAllowFileAccessFromFileURLsLocked();
1036         }
1037     }
1038
1039     @CalledByNative
1040     private boolean getAllowFileAccessFromFileURLsLocked() {
1041         assert Thread.holdsLock(mAwSettingsLock);
1042         return mAllowFileAccessFromFileURLs;
1043     }
1044
1045     /**
1046      * See {@link android.webkit.WebSettings#setPluginsEnabled}.
1047      */
1048     public void setPluginsEnabled(boolean flag) {
1049         setPluginState(flag ? PluginState.ON : PluginState.OFF);
1050     }
1051
1052     /**
1053      * See {@link android.webkit.WebSettings#setPluginState}.
1054      */
1055     public void setPluginState(PluginState state) {
1056         synchronized (mAwSettingsLock) {
1057             if (mPluginState != state) {
1058                 mPluginState = state;
1059                 mEventHandler.updateWebkitPreferencesLocked();
1060             }
1061         }
1062     }
1063
1064     /**
1065      * See {@link android.webkit.WebSettings#getPluginsEnabled}.
1066      */
1067     public boolean getPluginsEnabled() {
1068         synchronized (mAwSettingsLock) {
1069             return mPluginState == PluginState.ON;
1070         }
1071     }
1072
1073     /**
1074      * Return true if plugins are disabled.
1075      * @return True if plugins are disabled.
1076      */
1077     @CalledByNative
1078     private boolean getPluginsDisabledLocked() {
1079         assert Thread.holdsLock(mAwSettingsLock);
1080         return mPluginState == PluginState.OFF;
1081     }
1082
1083     /**
1084      * See {@link android.webkit.WebSettings#getPluginState}.
1085      */
1086     public PluginState getPluginState() {
1087         synchronized (mAwSettingsLock) {
1088             return mPluginState;
1089         }
1090     }
1091
1092
1093     /**
1094      * See {@link android.webkit.WebSettings#setJavaScriptCanOpenWindowsAutomatically}.
1095      */
1096     public void setJavaScriptCanOpenWindowsAutomatically(boolean flag) {
1097         synchronized (mAwSettingsLock) {
1098             if (mJavaScriptCanOpenWindowsAutomatically != flag) {
1099                 mJavaScriptCanOpenWindowsAutomatically = flag;
1100                 mEventHandler.updateWebkitPreferencesLocked();
1101             }
1102         }
1103     }
1104
1105     /**
1106      * See {@link android.webkit.WebSettings#getJavaScriptCanOpenWindowsAutomatically}.
1107      */
1108     public boolean getJavaScriptCanOpenWindowsAutomatically() {
1109         synchronized (mAwSettingsLock) {
1110             return getJavaScriptCanOpenWindowsAutomaticallyLocked();
1111         }
1112     }
1113
1114     @CalledByNative
1115     private boolean getJavaScriptCanOpenWindowsAutomaticallyLocked() {
1116         assert Thread.holdsLock(mAwSettingsLock);
1117         return mJavaScriptCanOpenWindowsAutomatically;
1118     }
1119
1120     /**
1121      * See {@link android.webkit.WebSettings#setLayoutAlgorithm}.
1122      */
1123     public void setLayoutAlgorithm(LayoutAlgorithm l) {
1124         synchronized (mAwSettingsLock) {
1125             if (mLayoutAlgorithm != l) {
1126                 mLayoutAlgorithm = l;
1127                 mEventHandler.updateWebkitPreferencesLocked();
1128             }
1129         }
1130     }
1131
1132     /**
1133      * See {@link android.webkit.WebSettings#getLayoutAlgorithm}.
1134      */
1135     public LayoutAlgorithm getLayoutAlgorithm() {
1136         synchronized (mAwSettingsLock) {
1137             return mLayoutAlgorithm;
1138         }
1139     }
1140
1141     /**
1142      * Gets whether Text Auto-sizing layout algorithm is enabled.
1143      *
1144      * @return true if Text Auto-sizing layout algorithm is enabled
1145      */
1146     @CalledByNative
1147     private boolean getTextAutosizingEnabledLocked() {
1148         assert Thread.holdsLock(mAwSettingsLock);
1149         return mLayoutAlgorithm == LayoutAlgorithm.TEXT_AUTOSIZING;
1150     }
1151
1152     /**
1153      * See {@link android.webkit.WebSettings#setSupportMultipleWindows}.
1154      */
1155     public void setSupportMultipleWindows(boolean support) {
1156         synchronized (mAwSettingsLock) {
1157             if (mSupportMultipleWindows != support) {
1158                 mSupportMultipleWindows = support;
1159                 mEventHandler.updateWebkitPreferencesLocked();
1160             }
1161         }
1162     }
1163
1164     /**
1165      * See {@link android.webkit.WebSettings#supportMultipleWindows}.
1166      */
1167     public boolean supportMultipleWindows() {
1168         synchronized (mAwSettingsLock) {
1169             return mSupportMultipleWindows;
1170         }
1171     }
1172
1173     @CalledByNative
1174     private boolean getSupportMultipleWindowsLocked() {
1175         assert Thread.holdsLock(mAwSettingsLock);
1176         return mSupportMultipleWindows;
1177     }
1178
1179     @CalledByNative
1180     private boolean getSupportLegacyQuirksLocked() {
1181         assert Thread.holdsLock(mAwSettingsLock);
1182         return mSupportLegacyQuirks;
1183     }
1184
1185     /**
1186      * See {@link android.webkit.WebSettings#setUseWideViewPort}.
1187      */
1188     public void setUseWideViewPort(boolean use) {
1189         synchronized (mAwSettingsLock) {
1190             if (mUseWideViewport != use) {
1191                 mUseWideViewport = use;
1192                 onGestureZoomSupportChanged(
1193                         supportsDoubleTapZoomLocked(), supportsMultiTouchZoomLocked());
1194                 mEventHandler.updateWebkitPreferencesLocked();
1195             }
1196         }
1197     }
1198
1199     /**
1200      * See {@link android.webkit.WebSettings#getUseWideViewPort}.
1201      */
1202     public boolean getUseWideViewPort() {
1203         synchronized (mAwSettingsLock) {
1204             return getUseWideViewportLocked();
1205         }
1206     }
1207
1208     @CalledByNative
1209     private boolean getUseWideViewportLocked() {
1210         assert Thread.holdsLock(mAwSettingsLock);
1211         return mUseWideViewport;
1212     }
1213
1214     @CalledByNative
1215     private boolean getPasswordEchoEnabledLocked() {
1216         assert Thread.holdsLock(mAwSettingsLock);
1217         return mPasswordEchoEnabled;
1218     }
1219
1220     /**
1221      * See {@link android.webkit.WebSettings#setAppCacheEnabled}.
1222      */
1223     public void setAppCacheEnabled(boolean flag) {
1224         synchronized (mAwSettingsLock) {
1225             if (mAppCacheEnabled != flag) {
1226                 mAppCacheEnabled = flag;
1227                 mEventHandler.updateWebkitPreferencesLocked();
1228             }
1229         }
1230     }
1231
1232     /**
1233      * See {@link android.webkit.WebSettings#setAppCachePath}.
1234      */
1235     public void setAppCachePath(String path) {
1236         boolean needToSync = false;
1237         synchronized (sGlobalContentSettingsLock) {
1238             // AppCachePath can only be set once.
1239             if (!sAppCachePathIsSet && path != null && !path.isEmpty()) {
1240                 sAppCachePathIsSet = true;
1241                 needToSync = true;
1242             }
1243         }
1244         // The obvious problem here is that other WebViews will not be updated,
1245         // until they execute synchronization from Java to the native side.
1246         // But this is the same behaviour as it was in the legacy WebView.
1247         if (needToSync) {
1248             synchronized (mAwSettingsLock) {
1249                 mEventHandler.updateWebkitPreferencesLocked();
1250             }
1251         }
1252     }
1253
1254     /**
1255      * Gets whether Application Cache is enabled.
1256      *
1257      * @return true if Application Cache is enabled
1258      */
1259     @CalledByNative
1260     private boolean getAppCacheEnabledLocked() {
1261         assert Thread.holdsLock(mAwSettingsLock);
1262         if (!mAppCacheEnabled) {
1263             return false;
1264         }
1265         synchronized (sGlobalContentSettingsLock) {
1266             return sAppCachePathIsSet;
1267         }
1268     }
1269
1270     /**
1271      * See {@link android.webkit.WebSettings#setDomStorageEnabled}.
1272      */
1273     public void setDomStorageEnabled(boolean flag) {
1274         synchronized (mAwSettingsLock) {
1275             if (mDomStorageEnabled != flag) {
1276                 mDomStorageEnabled = flag;
1277                 mEventHandler.updateWebkitPreferencesLocked();
1278             }
1279         }
1280     }
1281
1282     /**
1283      * See {@link android.webkit.WebSettings#getDomStorageEnabled}.
1284      */
1285     public boolean getDomStorageEnabled() {
1286         synchronized (mAwSettingsLock) {
1287             return mDomStorageEnabled;
1288         }
1289     }
1290
1291     @CalledByNative
1292     private boolean getDomStorageEnabledLocked() {
1293         assert Thread.holdsLock(mAwSettingsLock);
1294         return mDomStorageEnabled;
1295     }
1296
1297     /**
1298      * See {@link android.webkit.WebSettings#setDatabaseEnabled}.
1299      */
1300     public void setDatabaseEnabled(boolean flag) {
1301         synchronized (mAwSettingsLock) {
1302             if (mDatabaseEnabled != flag) {
1303                 mDatabaseEnabled = flag;
1304                 mEventHandler.updateWebkitPreferencesLocked();
1305             }
1306         }
1307     }
1308
1309     /**
1310      * See {@link android.webkit.WebSettings#getDatabaseEnabled}.
1311      */
1312     public boolean getDatabaseEnabled() {
1313         synchronized (mAwSettingsLock) {
1314             return mDatabaseEnabled;
1315         }
1316     }
1317
1318     @CalledByNative
1319     private boolean getDatabaseEnabledLocked() {
1320         assert Thread.holdsLock(mAwSettingsLock);
1321         return mDatabaseEnabled;
1322     }
1323
1324     /**
1325      * See {@link android.webkit.WebSettings#setDefaultTextEncodingName}.
1326      */
1327     public void setDefaultTextEncodingName(String encoding) {
1328         synchronized (mAwSettingsLock) {
1329             if (encoding != null && !mDefaultTextEncoding.equals(encoding)) {
1330                 mDefaultTextEncoding = encoding;
1331                 mEventHandler.updateWebkitPreferencesLocked();
1332             }
1333         }
1334     }
1335
1336     /**
1337      * See {@link android.webkit.WebSettings#getDefaultTextEncodingName}.
1338      */
1339     public String getDefaultTextEncodingName() {
1340         synchronized (mAwSettingsLock) {
1341             return getDefaultTextEncodingLocked();
1342         }
1343     }
1344
1345     @CalledByNative
1346     private String getDefaultTextEncodingLocked() {
1347         assert Thread.holdsLock(mAwSettingsLock);
1348         return mDefaultTextEncoding;
1349     }
1350
1351     /**
1352      * See {@link android.webkit.WebSettings#setMediaPlaybackRequiresUserGesture}.
1353      */
1354     public void setMediaPlaybackRequiresUserGesture(boolean require) {
1355         synchronized (mAwSettingsLock) {
1356             if (mMediaPlaybackRequiresUserGesture != require) {
1357                 mMediaPlaybackRequiresUserGesture = require;
1358                 mEventHandler.updateWebkitPreferencesLocked();
1359             }
1360         }
1361     }
1362
1363     /**
1364      * See {@link android.webkit.WebSettings#getMediaPlaybackRequiresUserGesture}.
1365      */
1366     public boolean getMediaPlaybackRequiresUserGesture() {
1367         synchronized (mAwSettingsLock) {
1368             return getMediaPlaybackRequiresUserGestureLocked();
1369         }
1370     }
1371
1372     @CalledByNative
1373     private boolean getMediaPlaybackRequiresUserGestureLocked() {
1374         assert Thread.holdsLock(mAwSettingsLock);
1375         return mMediaPlaybackRequiresUserGesture;
1376     }
1377
1378     /**
1379      * See {@link android.webkit.WebSettings#setDefaultVideoPosterURL}.
1380      */
1381     public void setDefaultVideoPosterURL(String url) {
1382         synchronized (mAwSettingsLock) {
1383             if (mDefaultVideoPosterURL != null && !mDefaultVideoPosterURL.equals(url) ||
1384                     mDefaultVideoPosterURL == null && url != null) {
1385                 mDefaultVideoPosterURL = url;
1386                 mEventHandler.updateWebkitPreferencesLocked();
1387             }
1388         }
1389     }
1390
1391     /**
1392      * See {@link android.webkit.WebSettings#getDefaultVideoPosterURL}.
1393      */
1394     public String getDefaultVideoPosterURL() {
1395         synchronized (mAwSettingsLock) {
1396             return getDefaultVideoPosterURLLocked();
1397         }
1398     }
1399
1400     @CalledByNative
1401     private String getDefaultVideoPosterURLLocked() {
1402         assert Thread.holdsLock(mAwSettingsLock);
1403         return mDefaultVideoPosterURL;
1404     }
1405
1406     private void onGestureZoomSupportChanged(
1407             final boolean supportsDoubleTapZoom, final boolean supportsMultiTouchZoom) {
1408         // Always post asynchronously here, to avoid doubling back onto the caller.
1409         mEventHandler.maybePostOnUiThread(new Runnable() {
1410             @Override
1411             public void run() {
1412                 synchronized (mAwSettingsLock) {
1413                     if (mZoomChangeListener != null) {
1414                         mZoomChangeListener.onGestureZoomSupportChanged(
1415                                 supportsDoubleTapZoom, supportsMultiTouchZoom);
1416                     }
1417                 }
1418             }
1419         });
1420     }
1421
1422     /**
1423      * See {@link android.webkit.WebSettings#setSupportZoom}.
1424      */
1425     public void setSupportZoom(boolean support) {
1426         synchronized (mAwSettingsLock) {
1427             if (mSupportZoom != support) {
1428                 mSupportZoom = support;
1429                 onGestureZoomSupportChanged(
1430                         supportsDoubleTapZoomLocked(), supportsMultiTouchZoomLocked());
1431             }
1432         }
1433     }
1434
1435     /**
1436      * See {@link android.webkit.WebSettings#supportZoom}.
1437      */
1438     public boolean supportZoom() {
1439         synchronized (mAwSettingsLock) {
1440             return mSupportZoom;
1441         }
1442     }
1443
1444     /**
1445      * See {@link android.webkit.WebSettings#setBuiltInZoomControls}.
1446      */
1447     public void setBuiltInZoomControls(boolean enabled) {
1448         synchronized (mAwSettingsLock) {
1449             if (mBuiltInZoomControls != enabled) {
1450                 mBuiltInZoomControls = enabled;
1451                 onGestureZoomSupportChanged(
1452                         supportsDoubleTapZoomLocked(), supportsMultiTouchZoomLocked());
1453             }
1454         }
1455     }
1456
1457     /**
1458      * See {@link android.webkit.WebSettings#getBuiltInZoomControls}.
1459      */
1460     public boolean getBuiltInZoomControls() {
1461         synchronized (mAwSettingsLock) {
1462             return mBuiltInZoomControls;
1463         }
1464     }
1465
1466     /**
1467      * See {@link android.webkit.WebSettings#setDisplayZoomControls}.
1468      */
1469     public void setDisplayZoomControls(boolean enabled) {
1470         synchronized (mAwSettingsLock) {
1471             mDisplayZoomControls = enabled;
1472         }
1473     }
1474
1475     /**
1476      * See {@link android.webkit.WebSettings#getDisplayZoomControls}.
1477      */
1478     public boolean getDisplayZoomControls() {
1479         synchronized (mAwSettingsLock) {
1480             return mDisplayZoomControls;
1481         }
1482     }
1483
1484     public void setMixedContentMode(int mode) {
1485         synchronized (mAwSettingsLock) {
1486             if (mMixedContentMode != mode) {
1487                 mMixedContentMode = mode;
1488                 mEventHandler.updateWebkitPreferencesLocked();
1489             }
1490         }
1491     }
1492
1493     public int getMixedContentMode() {
1494         synchronized (mAwSettingsLock) {
1495             return mMixedContentMode;
1496         }
1497     }
1498
1499     @CalledByNative
1500     private boolean getAllowRunningInsecureContentLocked() {
1501         assert Thread.holdsLock(mAwSettingsLock);
1502         return mMixedContentMode == MIXED_CONTENT_ALWAYS_ALLOW;
1503     }
1504
1505     @CalledByNative
1506     private boolean getAllowDisplayingInsecureContentLocked() {
1507         assert Thread.holdsLock(mAwSettingsLock);
1508         return mMixedContentMode == MIXED_CONTENT_ALWAYS_ALLOW ||
1509                 mMixedContentMode == MIXED_CONTENT_COMPATIBILITY_MODE;
1510     }
1511
1512     /**
1513      * Sets whether to use the video overlay for the embedded video.
1514      * @param flag whether to enable the video overlay for the embedded video.
1515      */
1516     public void setVideoOverlayForEmbeddedVideoEnabled(final boolean enabled) {
1517         synchronized (mAwSettingsLock) {
1518             if (mVideoOverlayForEmbeddedVideoEnabled != enabled) {
1519                 mVideoOverlayForEmbeddedVideoEnabled = enabled;
1520                 mEventHandler.runOnUiThreadBlockingAndLocked(new Runnable() {
1521                     @Override
1522                     public void run() {
1523                         if (mNativeAwSettings != 0) {
1524                             nativeUpdateRendererPreferencesLocked(mNativeAwSettings);
1525                         }
1526                     }
1527                 });
1528             }
1529         }
1530     }
1531
1532     /**
1533      * Gets whether to use the video overlay for the embedded video.
1534      * @return true if the WebView enables the video overlay for the embedded video.
1535      */
1536     public boolean getVideoOverlayForEmbeddedVideoEnabled() {
1537         synchronized (mAwSettingsLock) {
1538             return getVideoOverlayForEmbeddedVideoEnabledLocked();
1539         }
1540     }
1541
1542     @CalledByNative
1543     private boolean getVideoOverlayForEmbeddedVideoEnabledLocked() {
1544         assert Thread.holdsLock(mAwSettingsLock);
1545         return mVideoOverlayForEmbeddedVideoEnabled;
1546     }
1547
1548     @CalledByNative
1549     private boolean supportsDoubleTapZoomLocked() {
1550         assert Thread.holdsLock(mAwSettingsLock);
1551         return mSupportZoom && mBuiltInZoomControls && mUseWideViewport;
1552     }
1553
1554     private boolean supportsMultiTouchZoomLocked() {
1555         assert Thread.holdsLock(mAwSettingsLock);
1556         return mSupportZoom && mBuiltInZoomControls;
1557     }
1558
1559     boolean supportsMultiTouchZoom() {
1560         synchronized (mAwSettingsLock) {
1561             return supportsMultiTouchZoomLocked();
1562         }
1563     }
1564
1565     boolean shouldDisplayZoomControls() {
1566         synchronized (mAwSettingsLock) {
1567             return supportsMultiTouchZoomLocked() && mDisplayZoomControls;
1568         }
1569     }
1570
1571     private int clipFontSize(int size) {
1572         if (size < MINIMUM_FONT_SIZE) {
1573             return MINIMUM_FONT_SIZE;
1574         } else if (size > MAXIMUM_FONT_SIZE) {
1575             return MAXIMUM_FONT_SIZE;
1576         }
1577         return size;
1578     }
1579
1580     @CalledByNative
1581     private void updateEverything() {
1582         synchronized (mAwSettingsLock) {
1583             updateEverythingLocked();
1584         }
1585     }
1586
1587     @CalledByNative
1588     private void populateWebPreferences(long webPrefsPtr) {
1589         synchronized (mAwSettingsLock) {
1590             assert mNativeAwSettings != 0;
1591             nativePopulateWebPreferencesLocked(mNativeAwSettings, webPrefsPtr);
1592         }
1593     }
1594
1595     private void updateWebkitPreferencesOnUiThreadLocked() {
1596         assert mEventHandler.mHandler != null;
1597         ThreadUtils.assertOnUiThread();
1598         if (mNativeAwSettings != 0) {
1599             nativeUpdateWebkitPreferencesLocked(mNativeAwSettings);
1600         }
1601     }
1602
1603     private native long nativeInit(long webContentsPtr);
1604
1605     private native void nativeDestroy(long nativeAwSettings);
1606
1607     private native void nativePopulateWebPreferencesLocked(long nativeAwSettings, long webPrefsPtr);
1608
1609     private native void nativeResetScrollAndScaleState(long nativeAwSettings);
1610
1611     private native void nativeUpdateEverythingLocked(long nativeAwSettings);
1612
1613     private native void nativeUpdateInitialPageScaleLocked(long nativeAwSettings);
1614
1615     private native void nativeUpdateUserAgentLocked(long nativeAwSettings);
1616
1617     private native void nativeUpdateWebkitPreferencesLocked(long nativeAwSettings);
1618
1619     private static native String nativeGetDefaultUserAgent();
1620
1621     private native void nativeUpdateFormDataPreferencesLocked(long nativeAwSettings);
1622
1623     private native void nativeUpdateRendererPreferencesLocked(long nativeAwSettings);
1624 }