// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import android.provider.Settings;
import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebSettings.PluginState;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.ThreadUtils;
/**
* Stores Android WebView specific settings that does not need to be synced to WebKit.
* Use {@link org.chromium.content.browser.ContentSettings} for WebKit settings.
*
* Methods in this class can be called from any thread, including threads created by
* the client of WebView.
*/
@JNINamespace("android_webview")
public class AwSettings {
// This enum corresponds to WebSettings.LayoutAlgorithm. We use our own to be
// able to extend it.
public enum LayoutAlgorithm {
NORMAL,
SINGLE_COLUMN,
NARROW_COLUMNS,
TEXT_AUTOSIZING,
}
private static final String TAG = "AwSettings";
// This class must be created on the UI thread. Afterwards, it can be
// used from any thread. Internally, the class uses a message queue
// to call native code on the UI thread only.
// Values passed in on construction.
private final boolean mHasInternetPermission;
private ZoomSupportChangeListener mZoomChangeListener;
private double mDIPScale = 1.0;
// Lock to protect all settings.
private final Object mAwSettingsLock = new Object();
private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
private int mTextSizePercent = 100;
private String mStandardFontFamily = "sans-serif";
private String mFixedFontFamily = "monospace";
private String mSansSerifFontFamily = "sans-serif";
private String mSerifFontFamily = "serif";
private String mCursiveFontFamily = "cursive";
private String mFantasyFontFamily = "fantasy";
private String mDefaultTextEncoding;
private String mUserAgent;
private int mMinimumFontSize = 8;
private int mMinimumLogicalFontSize = 8;
private int mDefaultFontSize = 16;
private int mDefaultFixedFontSize = 13;
private boolean mLoadsImagesAutomatically = true;
private boolean mImagesEnabled = true;
private boolean mJavaScriptEnabled = false;
private boolean mAllowUniversalAccessFromFileURLs = false;
private boolean mAllowFileAccessFromFileURLs = false;
private boolean mJavaScriptCanOpenWindowsAutomatically = false;
private boolean mSupportMultipleWindows = false;
private PluginState mPluginState = PluginState.OFF;
private boolean mAppCacheEnabled = false;
private boolean mDomStorageEnabled = false;
private boolean mDatabaseEnabled = false;
private boolean mUseWideViewport = false;
private boolean mLoadWithOverviewMode = false;
private boolean mMediaPlaybackRequiresUserGesture = true;
private String mDefaultVideoPosterURL;
private float mInitialPageScalePercent = 0;
private boolean mSpatialNavigationEnabled; // Default depends on device features.
private boolean mEnableSupportedHardwareAcceleratedFeatures = false;
private final boolean mSupportLegacyQuirks;
private final boolean mPasswordEchoEnabled;
// Not accessed by the native side.
private boolean mBlockNetworkLoads; // Default depends on permission of embedding APK.
private boolean mAllowContentUrlAccess = true;
private boolean mAllowFileUrlAccess = true;
private int mCacheMode = WebSettings.LOAD_DEFAULT;
private boolean mShouldFocusFirstNode = true;
private boolean mGeolocationEnabled = true;
private boolean mAutoCompleteEnabled = true;
private boolean mSupportZoom = true;
private boolean mBuiltInZoomControls = false;
private boolean mDisplayZoomControls = true;
static class LazyDefaultUserAgent{
// Lazy Holder pattern
private static final String sInstance = nativeGetDefaultUserAgent();
}
// Protects access to settings global fields.
private static final Object sGlobalContentSettingsLock = new Object();
// For compatibility with the legacy WebView, we can only enable AppCache when the path is
// provided. However, we don't use the path, so we just check if we have received it from the
// client.
private static boolean sAppCachePathIsSet = false;
// The native side of this object. It's lifetime is bounded by the WebContent it is attached to.
private long mNativeAwSettings = 0;
// Custom handler that queues messages to call native code on the UI thread.
private final EventHandler mEventHandler;
private static final int MINIMUM_FONT_SIZE = 1;
private static final int MAXIMUM_FONT_SIZE = 72;
// Class to handle messages to be processed on the UI thread.
private class EventHandler {
// Message id for running a Runnable with mAwSettingsLock held.
private static final int RUN_RUNNABLE_BLOCKING = 0;
// Actual UI thread handler
private Handler mHandler;
// Synchronization flag.
private boolean mSynchronizationPending = false;
EventHandler() {
}
void bindUiThread() {
if (mHandler != null) return;
mHandler = new Handler(ThreadUtils.getUiThreadLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case RUN_RUNNABLE_BLOCKING:
synchronized (mAwSettingsLock) {
if (mNativeAwSettings != 0) {
((Runnable)msg.obj).run();
}
mSynchronizationPending = false;
mAwSettingsLock.notifyAll();
}
break;
}
}
};
}
void runOnUiThreadBlockingAndLocked(Runnable r) {
assert Thread.holdsLock(mAwSettingsLock);
if (mHandler == null) return;
if (ThreadUtils.runningOnUiThread()) {
r.run();
} else {
assert !mSynchronizationPending;
mSynchronizationPending = true;
mHandler.sendMessage(Message.obtain(null, RUN_RUNNABLE_BLOCKING, r));
try {
while (mSynchronizationPending) {
mAwSettingsLock.wait();
}
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted waiting a Runnable to complete", e);
mSynchronizationPending = false;
}
}
}
void maybePostOnUiThread(Runnable r) {
if (mHandler != null) {
mHandler.post(r);
}
}
void updateWebkitPreferencesLocked() {
runOnUiThreadBlockingAndLocked(new Runnable() {
@Override
public void run() {
updateWebkitPreferencesOnUiThreadLocked();
}
});
}
}
interface ZoomSupportChangeListener {
public void onGestureZoomSupportChanged(
boolean supportsDoubleTapZoom, boolean supportsMultiTouchZoom);
}
public AwSettings(Context context,
boolean isAccessFromFileURLsGrantedByDefault,
boolean supportsLegacyQuirks) {
boolean hasInternetPermission = context.checkPermission(
android.Manifest.permission.INTERNET,
Process.myPid(),
Process.myUid()) == PackageManager.PERMISSION_GRANTED;
synchronized (mAwSettingsLock) {
mHasInternetPermission = hasInternetPermission;
mBlockNetworkLoads = !hasInternetPermission;
mEventHandler = new EventHandler();
if (isAccessFromFileURLsGrantedByDefault) {
mAllowUniversalAccessFromFileURLs = true;
mAllowFileAccessFromFileURLs = true;
}
mDefaultTextEncoding = AwResource.getDefaultTextEncoding();
mUserAgent = LazyDefaultUserAgent.sInstance;
// Best-guess a sensible initial value based on the features supported on the device.
mSpatialNavigationEnabled = !context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TOUCHSCREEN);
// Respect the system setting for password echoing.
mPasswordEchoEnabled = Settings.System.getInt(context.getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
// By default, scale the text size by the system font scale factor. Embedders
// may override this by invoking setTextZoom().
mTextSizePercent *= context.getResources().getConfiguration().fontScale;
mSupportLegacyQuirks = supportsLegacyQuirks;
}
// Defer initializing the native side until a native WebContents instance is set.
}
@CalledByNative
private void nativeAwSettingsGone(long nativeAwSettings) {
assert mNativeAwSettings != 0 && mNativeAwSettings == nativeAwSettings;
mNativeAwSettings = 0;
}
@CalledByNative
private double getDIPScaleLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mDIPScale;
}
void setDIPScale(double dipScale) {
synchronized (mAwSettingsLock) {
mDIPScale = dipScale;
// TODO(joth): This should also be synced over to native side, but right now
// the setDIPScale call is always followed by a setWebContents() which covers this.
}
}
void setZoomListener(ZoomSupportChangeListener zoomChangeListener) {
synchronized (mAwSettingsLock) {
mZoomChangeListener = zoomChangeListener;
}
}
void setWebContents(int nativeWebContents) {
synchronized (mAwSettingsLock) {
if (mNativeAwSettings != 0) {
nativeDestroy(mNativeAwSettings);
assert mNativeAwSettings == 0; // nativeAwSettingsGone should have been called.
}
if (nativeWebContents != 0) {
mEventHandler.bindUiThread();
mNativeAwSettings = nativeInit(nativeWebContents);
nativeUpdateEverythingLocked(mNativeAwSettings);
onGestureZoomSupportChanged(
supportsDoubleTapZoomLocked(), supportsMultiTouchZoomLocked());
}
}
}
/**
* See {@link android.webkit.WebSettings#setBlockNetworkLoads}.
*/
public void setBlockNetworkLoads(boolean flag) {
synchronized (mAwSettingsLock) {
if (!flag && !mHasInternetPermission) {
throw new SecurityException("Permission denied - " +
"application missing INTERNET permission");
}
mBlockNetworkLoads = flag;
}
}
/**
* See {@link android.webkit.WebSettings#getBlockNetworkLoads}.
*/
public boolean getBlockNetworkLoads() {
synchronized (mAwSettingsLock) {
return mBlockNetworkLoads;
}
}
/**
* See {@link android.webkit.WebSettings#setAllowFileAccess}.
*/
public void setAllowFileAccess(boolean allow) {
synchronized (mAwSettingsLock) {
if (mAllowFileUrlAccess != allow) {
mAllowFileUrlAccess = allow;
}
}
}
/**
* See {@link android.webkit.WebSettings#getAllowFileAccess}.
*/
public boolean getAllowFileAccess() {
synchronized (mAwSettingsLock) {
return mAllowFileUrlAccess;
}
}
/**
* See {@link android.webkit.WebSettings#setAllowContentAccess}.
*/
public void setAllowContentAccess(boolean allow) {
synchronized (mAwSettingsLock) {
if (mAllowContentUrlAccess != allow) {
mAllowContentUrlAccess = allow;
}
}
}
/**
* See {@link android.webkit.WebSettings#getAllowContentAccess}.
*/
public boolean getAllowContentAccess() {
synchronized (mAwSettingsLock) {
return mAllowContentUrlAccess;
}
}
/**
* See {@link android.webkit.WebSettings#setCacheMode}.
*/
public void setCacheMode(int mode) {
synchronized (mAwSettingsLock) {
if (mCacheMode != mode) {
mCacheMode = mode;
}
}
}
/**
* See {@link android.webkit.WebSettings#getCacheMode}.
*/
public int getCacheMode() {
synchronized (mAwSettingsLock) {
return mCacheMode;
}
}
/**
* See {@link android.webkit.WebSettings#setNeedInitialFocus}.
*/
public void setShouldFocusFirstNode(boolean flag) {
synchronized (mAwSettingsLock) {
mShouldFocusFirstNode = flag;
}
}
/**
* See {@link android.webkit.WebView#setInitialScale}.
*/
public void setInitialPageScale(final float scaleInPercent) {
synchronized (mAwSettingsLock) {
if (mInitialPageScalePercent != scaleInPercent) {
mInitialPageScalePercent = scaleInPercent;
mEventHandler.runOnUiThreadBlockingAndLocked(new Runnable() {
@Override
public void run() {
nativeUpdateInitialPageScaleLocked(mNativeAwSettings);
}
});
}
}
}
@CalledByNative
private float getInitialPageScalePercentLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mInitialPageScalePercent;
}
void setSpatialNavigationEnabled(boolean enable) {
synchronized (mAwSettingsLock) {
if (mSpatialNavigationEnabled != enable) {
mSpatialNavigationEnabled = enable;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
@CalledByNative
private boolean getSpatialNavigationLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mSpatialNavigationEnabled;
}
void setEnableSupportedHardwareAcceleratedFeatures(boolean enable) {
synchronized (mAwSettingsLock) {
if (mEnableSupportedHardwareAcceleratedFeatures != enable) {
mEnableSupportedHardwareAcceleratedFeatures = enable;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
@CalledByNative
private boolean getEnableSupportedHardwareAcceleratedFeaturesLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mEnableSupportedHardwareAcceleratedFeatures;
}
/**
* See {@link android.webkit.WebSettings#setNeedInitialFocus}.
*/
public boolean shouldFocusFirstNode() {
synchronized (mAwSettingsLock) {
return mShouldFocusFirstNode;
}
}
/**
* See {@link android.webkit.WebSettings#setGeolocationEnabled}.
*/
public void setGeolocationEnabled(boolean flag) {
synchronized (mAwSettingsLock) {
if (mGeolocationEnabled != flag) {
mGeolocationEnabled = flag;
}
}
}
/**
* @return Returns if geolocation is currently enabled.
*/
boolean getGeolocationEnabled() {
synchronized (mAwSettingsLock) {
return mGeolocationEnabled;
}
}
/**
* See {@link android.webkit.WebSettings#setSaveFormData}.
*/
public void setSaveFormData(final boolean enable) {
synchronized (mAwSettingsLock) {
if (mAutoCompleteEnabled != enable) {
mAutoCompleteEnabled = enable;
mEventHandler.runOnUiThreadBlockingAndLocked(new Runnable() {
@Override
public void run() {
nativeUpdateFormDataPreferencesLocked(mNativeAwSettings);
}
});
}
}
}
/**
* See {@link android.webkit.WebSettings#getSaveFormData}.
*/
public boolean getSaveFormData() {
synchronized (mAwSettingsLock) {
return getSaveFormDataLocked();
}
}
@CalledByNative
private boolean getSaveFormDataLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mAutoCompleteEnabled;
}
/**
* @returns the default User-Agent used by each ContentViewCore instance, i.e. unless
* overridden by {@link #setUserAgentString()}
*/
public static String getDefaultUserAgent() {
return LazyDefaultUserAgent.sInstance;
}
/**
* See {@link android.webkit.WebSettings#setUserAgentString}.
*/
public void setUserAgentString(String ua) {
synchronized (mAwSettingsLock) {
final String oldUserAgent = mUserAgent;
if (ua == null || ua.length() == 0) {
mUserAgent = LazyDefaultUserAgent.sInstance;
} else {
mUserAgent = ua;
}
if (!oldUserAgent.equals(mUserAgent)) {
mEventHandler.runOnUiThreadBlockingAndLocked(new Runnable() {
@Override
public void run() {
nativeUpdateUserAgentLocked(mNativeAwSettings);
}
});
}
}
}
/**
* See {@link android.webkit.WebSettings#getUserAgentString}.
*/
public String getUserAgentString() {
synchronized (mAwSettingsLock) {
return mUserAgent;
}
}
@CalledByNative
private String getUserAgentLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mUserAgent;
}
/**
* See {@link android.webkit.WebSettings#setLoadWithOverviewMode}.
*/
public void setLoadWithOverviewMode(boolean overview) {
synchronized (mAwSettingsLock) {
if (mLoadWithOverviewMode != overview) {
mLoadWithOverviewMode = overview;
mEventHandler.runOnUiThreadBlockingAndLocked(new Runnable() {
@Override
public void run() {
updateWebkitPreferencesOnUiThreadLocked();
nativeResetScrollAndScaleState(mNativeAwSettings);
}
});
}
}
}
/**
* See {@link android.webkit.WebSettings#getLoadWithOverviewMode}.
*/
public boolean getLoadWithOverviewMode() {
synchronized (mAwSettingsLock) {
return mLoadWithOverviewMode;
}
}
@CalledByNative
private boolean getLoadWithOverviewModeLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mLoadWithOverviewMode;
}
/**
* See {@link android.webkit.WebSettings#setTextZoom}.
*/
public void setTextZoom(final int textZoom) {
synchronized (mAwSettingsLock) {
if (mTextSizePercent != textZoom) {
mTextSizePercent = textZoom;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getTextZoom}.
*/
public int getTextZoom() {
synchronized (mAwSettingsLock) {
return mTextSizePercent;
}
}
@CalledByNative
private int getTextSizePercentLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mTextSizePercent;
}
/**
* See {@link android.webkit.WebSettings#setStandardFontFamily}.
*/
public void setStandardFontFamily(String font) {
synchronized (mAwSettingsLock) {
if (font != null && !mStandardFontFamily.equals(font)) {
mStandardFontFamily = font;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getStandardFontFamily}.
*/
public String getStandardFontFamily() {
synchronized (mAwSettingsLock) {
return mStandardFontFamily;
}
}
@CalledByNative
private String getStandardFontFamilyLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mStandardFontFamily;
}
/**
* See {@link android.webkit.WebSettings#setFixedFontFamily}.
*/
public void setFixedFontFamily(String font) {
synchronized (mAwSettingsLock) {
if (font != null && !mFixedFontFamily.equals(font)) {
mFixedFontFamily = font;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getFixedFontFamily}.
*/
public String getFixedFontFamily() {
synchronized (mAwSettingsLock) {
return mFixedFontFamily;
}
}
@CalledByNative
private String getFixedFontFamilyLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mFixedFontFamily;
}
/**
* See {@link android.webkit.WebSettings#setSansSerifFontFamily}.
*/
public void setSansSerifFontFamily(String font) {
synchronized (mAwSettingsLock) {
if (font != null && !mSansSerifFontFamily.equals(font)) {
mSansSerifFontFamily = font;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getSansSerifFontFamily}.
*/
public String getSansSerifFontFamily() {
synchronized (mAwSettingsLock) {
return mSansSerifFontFamily;
}
}
@CalledByNative
private String getSansSerifFontFamilyLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mSansSerifFontFamily;
}
/**
* See {@link android.webkit.WebSettings#setSerifFontFamily}.
*/
public void setSerifFontFamily(String font) {
synchronized (mAwSettingsLock) {
if (font != null && !mSerifFontFamily.equals(font)) {
mSerifFontFamily = font;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getSerifFontFamily}.
*/
public String getSerifFontFamily() {
synchronized (mAwSettingsLock) {
return mSerifFontFamily;
}
}
@CalledByNative
private String getSerifFontFamilyLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mSerifFontFamily;
}
/**
* See {@link android.webkit.WebSettings#setCursiveFontFamily}.
*/
public void setCursiveFontFamily(String font) {
synchronized (mAwSettingsLock) {
if (font != null && !mCursiveFontFamily.equals(font)) {
mCursiveFontFamily = font;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getCursiveFontFamily}.
*/
public String getCursiveFontFamily() {
synchronized (mAwSettingsLock) {
return mCursiveFontFamily;
}
}
@CalledByNative
private String getCursiveFontFamilyLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mCursiveFontFamily;
}
/**
* See {@link android.webkit.WebSettings#setFantasyFontFamily}.
*/
public void setFantasyFontFamily(String font) {
synchronized (mAwSettingsLock) {
if (font != null && !mFantasyFontFamily.equals(font)) {
mFantasyFontFamily = font;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getFantasyFontFamily}.
*/
public String getFantasyFontFamily() {
synchronized (mAwSettingsLock) {
return mFantasyFontFamily;
}
}
@CalledByNative
private String getFantasyFontFamilyLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mFantasyFontFamily;
}
/**
* See {@link android.webkit.WebSettings#setMinimumFontSize}.
*/
public void setMinimumFontSize(int size) {
synchronized (mAwSettingsLock) {
size = clipFontSize(size);
if (mMinimumFontSize != size) {
mMinimumFontSize = size;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getMinimumFontSize}.
*/
public int getMinimumFontSize() {
synchronized (mAwSettingsLock) {
return mMinimumFontSize;
}
}
@CalledByNative
private int getMinimumFontSizeLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mMinimumFontSize;
}
/**
* See {@link android.webkit.WebSettings#setMinimumLogicalFontSize}.
*/
public void setMinimumLogicalFontSize(int size) {
synchronized (mAwSettingsLock) {
size = clipFontSize(size);
if (mMinimumLogicalFontSize != size) {
mMinimumLogicalFontSize = size;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getMinimumLogicalFontSize}.
*/
public int getMinimumLogicalFontSize() {
synchronized (mAwSettingsLock) {
return mMinimumLogicalFontSize;
}
}
@CalledByNative
private int getMinimumLogicalFontSizeLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mMinimumLogicalFontSize;
}
/**
* See {@link android.webkit.WebSettings#setDefaultFontSize}.
*/
public void setDefaultFontSize(int size) {
synchronized (mAwSettingsLock) {
size = clipFontSize(size);
if (mDefaultFontSize != size) {
mDefaultFontSize = size;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getDefaultFontSize}.
*/
public int getDefaultFontSize() {
synchronized (mAwSettingsLock) {
return mDefaultFontSize;
}
}
@CalledByNative
private int getDefaultFontSizeLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mDefaultFontSize;
}
/**
* See {@link android.webkit.WebSettings#setDefaultFixedFontSize}.
*/
public void setDefaultFixedFontSize(int size) {
synchronized (mAwSettingsLock) {
size = clipFontSize(size);
if (mDefaultFixedFontSize != size) {
mDefaultFixedFontSize = size;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getDefaultFixedFontSize}.
*/
public int getDefaultFixedFontSize() {
synchronized (mAwSettingsLock) {
return mDefaultFixedFontSize;
}
}
@CalledByNative
private int getDefaultFixedFontSizeLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mDefaultFixedFontSize;
}
/**
* See {@link android.webkit.WebSettings#setJavaScriptEnabled}.
*/
public void setJavaScriptEnabled(boolean flag) {
synchronized (mAwSettingsLock) {
if (mJavaScriptEnabled != flag) {
mJavaScriptEnabled = flag;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#setAllowUniversalAccessFromFileURLs}.
*/
public void setAllowUniversalAccessFromFileURLs(boolean flag) {
synchronized (mAwSettingsLock) {
if (mAllowUniversalAccessFromFileURLs != flag) {
mAllowUniversalAccessFromFileURLs = flag;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#setAllowFileAccessFromFileURLs}.
*/
public void setAllowFileAccessFromFileURLs(boolean flag) {
synchronized (mAwSettingsLock) {
if (mAllowFileAccessFromFileURLs != flag) {
mAllowFileAccessFromFileURLs = flag;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#setLoadsImagesAutomatically}.
*/
public void setLoadsImagesAutomatically(boolean flag) {
synchronized (mAwSettingsLock) {
if (mLoadsImagesAutomatically != flag) {
mLoadsImagesAutomatically = flag;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getLoadsImagesAutomatically}.
*/
public boolean getLoadsImagesAutomatically() {
synchronized (mAwSettingsLock) {
return mLoadsImagesAutomatically;
}
}
@CalledByNative
private boolean getLoadsImagesAutomaticallyLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mLoadsImagesAutomatically;
}
/**
* See {@link android.webkit.WebSettings#setImagesEnabled}.
*/
public void setImagesEnabled(boolean flag) {
synchronized (mAwSettingsLock) {
if (mImagesEnabled != flag) {
mImagesEnabled = flag;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getImagesEnabled}.
*/
public boolean getImagesEnabled() {
synchronized (mAwSettingsLock) {
return mImagesEnabled;
}
}
@CalledByNative
private boolean getImagesEnabledLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mImagesEnabled;
}
/**
* See {@link android.webkit.WebSettings#getJavaScriptEnabled}.
*/
public boolean getJavaScriptEnabled() {
synchronized (mAwSettingsLock) {
return mJavaScriptEnabled;
}
}
@CalledByNative
private boolean getJavaScriptEnabledLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mJavaScriptEnabled;
}
/**
* See {@link android.webkit.WebSettings#getAllowUniversalAccessFromFileURLs}.
*/
public boolean getAllowUniversalAccessFromFileURLs() {
synchronized (mAwSettingsLock) {
return mAllowUniversalAccessFromFileURLs;
}
}
@CalledByNative
private boolean getAllowUniversalAccessFromFileURLsLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mAllowUniversalAccessFromFileURLs;
}
/**
* See {@link android.webkit.WebSettings#getAllowFileAccessFromFileURLs}.
*/
public boolean getAllowFileAccessFromFileURLs() {
synchronized (mAwSettingsLock) {
return mAllowFileAccessFromFileURLs;
}
}
@CalledByNative
private boolean getAllowFileAccessFromFileURLsLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mAllowFileAccessFromFileURLs;
}
/**
* See {@link android.webkit.WebSettings#setPluginsEnabled}.
*/
public void setPluginsEnabled(boolean flag) {
setPluginState(flag ? PluginState.ON : PluginState.OFF);
}
/**
* See {@link android.webkit.WebSettings#setPluginState}.
*/
public void setPluginState(PluginState state) {
synchronized (mAwSettingsLock) {
if (mPluginState != state) {
mPluginState = state;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getPluginsEnabled}.
*/
public boolean getPluginsEnabled() {
synchronized (mAwSettingsLock) {
return mPluginState == PluginState.ON;
}
}
/**
* Return true if plugins are disabled.
* @return True if plugins are disabled.
*/
@CalledByNative
private boolean getPluginsDisabledLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mPluginState == PluginState.OFF;
}
/**
* See {@link android.webkit.WebSettings#getPluginState}.
*/
public PluginState getPluginState() {
synchronized (mAwSettingsLock) {
return mPluginState;
}
}
/**
* See {@link android.webkit.WebSettings#setJavaScriptCanOpenWindowsAutomatically}.
*/
public void setJavaScriptCanOpenWindowsAutomatically(boolean flag) {
synchronized (mAwSettingsLock) {
if (mJavaScriptCanOpenWindowsAutomatically != flag) {
mJavaScriptCanOpenWindowsAutomatically = flag;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getJavaScriptCanOpenWindowsAutomatically}.
*/
public boolean getJavaScriptCanOpenWindowsAutomatically() {
synchronized (mAwSettingsLock) {
return mJavaScriptCanOpenWindowsAutomatically;
}
}
@CalledByNative
private boolean getJavaScriptCanOpenWindowsAutomaticallyLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mJavaScriptCanOpenWindowsAutomatically;
}
/**
* See {@link android.webkit.WebSettings#setLayoutAlgorithm}.
*/
public void setLayoutAlgorithm(LayoutAlgorithm l) {
synchronized (mAwSettingsLock) {
if (mLayoutAlgorithm != l) {
mLayoutAlgorithm = l;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getLayoutAlgorithm}.
*/
public LayoutAlgorithm getLayoutAlgorithm() {
synchronized (mAwSettingsLock) {
return mLayoutAlgorithm;
}
}
/**
* Gets whether Text Auto-sizing layout algorithm is enabled.
*
* @return true if Text Auto-sizing layout algorithm is enabled
*/
@CalledByNative
private boolean getTextAutosizingEnabledLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mLayoutAlgorithm == LayoutAlgorithm.TEXT_AUTOSIZING;
}
/**
* See {@link android.webkit.WebSettings#setSupportMultipleWindows}.
*/
public void setSupportMultipleWindows(boolean support) {
synchronized (mAwSettingsLock) {
if (mSupportMultipleWindows != support) {
mSupportMultipleWindows = support;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#supportMultipleWindows}.
*/
public boolean supportMultipleWindows() {
synchronized (mAwSettingsLock) {
return mSupportMultipleWindows;
}
}
@CalledByNative
private boolean getSupportMultipleWindowsLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mSupportMultipleWindows;
}
@CalledByNative
private boolean getSupportLegacyQuirksLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mSupportLegacyQuirks;
}
/**
* See {@link android.webkit.WebSettings#setUseWideViewPort}.
*/
public void setUseWideViewPort(boolean use) {
synchronized (mAwSettingsLock) {
if (mUseWideViewport != use) {
mUseWideViewport = use;
onGestureZoomSupportChanged(
supportsDoubleTapZoomLocked(), supportsMultiTouchZoomLocked());
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getUseWideViewPort}.
*/
public boolean getUseWideViewPort() {
synchronized (mAwSettingsLock) {
return mUseWideViewport;
}
}
@CalledByNative
private boolean getUseWideViewportLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mUseWideViewport;
}
@CalledByNative
private boolean getPasswordEchoEnabledLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mPasswordEchoEnabled;
}
/**
* See {@link android.webkit.WebSettings#setAppCacheEnabled}.
*/
public void setAppCacheEnabled(boolean flag) {
synchronized (mAwSettingsLock) {
if (mAppCacheEnabled != flag) {
mAppCacheEnabled = flag;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#setAppCachePath}.
*/
public void setAppCachePath(String path) {
boolean needToSync = false;
synchronized (sGlobalContentSettingsLock) {
// AppCachePath can only be set once.
if (!sAppCachePathIsSet && path != null && !path.isEmpty()) {
sAppCachePathIsSet = true;
needToSync = true;
}
}
// The obvious problem here is that other WebViews will not be updated,
// until they execute synchronization from Java to the native side.
// But this is the same behaviour as it was in the legacy WebView.
if (needToSync) {
synchronized (mAwSettingsLock) {
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* Gets whether Application Cache is enabled.
*
* @return true if Application Cache is enabled
*/
@CalledByNative
private boolean getAppCacheEnabledLocked() {
assert Thread.holdsLock(mAwSettingsLock);
if (!mAppCacheEnabled) {
return false;
}
synchronized (sGlobalContentSettingsLock) {
return sAppCachePathIsSet;
}
}
/**
* See {@link android.webkit.WebSettings#setDomStorageEnabled}.
*/
public void setDomStorageEnabled(boolean flag) {
synchronized (mAwSettingsLock) {
if (mDomStorageEnabled != flag) {
mDomStorageEnabled = flag;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getDomStorageEnabled}.
*/
public boolean getDomStorageEnabled() {
synchronized (mAwSettingsLock) {
return mDomStorageEnabled;
}
}
@CalledByNative
private boolean getDomStorageEnabledLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mDomStorageEnabled;
}
/**
* See {@link android.webkit.WebSettings#setDatabaseEnabled}.
*/
public void setDatabaseEnabled(boolean flag) {
synchronized (mAwSettingsLock) {
if (mDatabaseEnabled != flag) {
mDatabaseEnabled = flag;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getDatabaseEnabled}.
*/
public boolean getDatabaseEnabled() {
synchronized (mAwSettingsLock) {
return mDatabaseEnabled;
}
}
@CalledByNative
private boolean getDatabaseEnabledLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mDatabaseEnabled;
}
/**
* See {@link android.webkit.WebSettings#setDefaultTextEncodingName}.
*/
public void setDefaultTextEncodingName(String encoding) {
synchronized (mAwSettingsLock) {
if (encoding != null && !mDefaultTextEncoding.equals(encoding)) {
mDefaultTextEncoding = encoding;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getDefaultTextEncodingName}.
*/
public String getDefaultTextEncodingName() {
synchronized (mAwSettingsLock) {
return mDefaultTextEncoding;
}
}
@CalledByNative
private String getDefaultTextEncodingLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mDefaultTextEncoding;
}
/**
* See {@link android.webkit.WebSettings#setMediaPlaybackRequiresUserGesture}.
*/
public void setMediaPlaybackRequiresUserGesture(boolean require) {
synchronized (mAwSettingsLock) {
if (mMediaPlaybackRequiresUserGesture != require) {
mMediaPlaybackRequiresUserGesture = require;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getMediaPlaybackRequiresUserGesture}.
*/
public boolean getMediaPlaybackRequiresUserGesture() {
synchronized (mAwSettingsLock) {
return mMediaPlaybackRequiresUserGesture;
}
}
@CalledByNative
private boolean getMediaPlaybackRequiresUserGestureLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mMediaPlaybackRequiresUserGesture;
}
/**
* See {@link android.webkit.WebSettings#setDefaultVideoPosterURL}.
*/
public void setDefaultVideoPosterURL(String url) {
synchronized (mAwSettingsLock) {
if (mDefaultVideoPosterURL != null && !mDefaultVideoPosterURL.equals(url) ||
mDefaultVideoPosterURL == null && url != null) {
mDefaultVideoPosterURL = url;
mEventHandler.updateWebkitPreferencesLocked();
}
}
}
/**
* See {@link android.webkit.WebSettings#getDefaultVideoPosterURL}.
*/
public String getDefaultVideoPosterURL() {
synchronized (mAwSettingsLock) {
return mDefaultVideoPosterURL;
}
}
@CalledByNative
private String getDefaultVideoPosterURLLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mDefaultVideoPosterURL;
}
private void onGestureZoomSupportChanged(
final boolean supportsDoubleTapZoom, final boolean supportsMultiTouchZoom) {
// Always post asynchronously here, to avoid doubling back onto the caller.
mEventHandler.maybePostOnUiThread(new Runnable() {
@Override
public void run() {
synchronized (mAwSettingsLock) {
if (mZoomChangeListener != null) {
mZoomChangeListener.onGestureZoomSupportChanged(
supportsDoubleTapZoom, supportsMultiTouchZoom);
}
}
}
});
}
/**
* See {@link android.webkit.WebSettings#setSupportZoom}.
*/
public void setSupportZoom(boolean support) {
synchronized (mAwSettingsLock) {
if (mSupportZoom != support) {
mSupportZoom = support;
onGestureZoomSupportChanged(
supportsDoubleTapZoomLocked(), supportsMultiTouchZoomLocked());
}
}
}
/**
* See {@link android.webkit.WebSettings#supportZoom}.
*/
public boolean supportZoom() {
synchronized (mAwSettingsLock) {
return mSupportZoom;
}
}
/**
* See {@link android.webkit.WebSettings#setBuiltInZoomControls}.
*/
public void setBuiltInZoomControls(boolean enabled) {
synchronized (mAwSettingsLock) {
if (mBuiltInZoomControls != enabled) {
mBuiltInZoomControls = enabled;
onGestureZoomSupportChanged(
supportsDoubleTapZoomLocked(), supportsMultiTouchZoomLocked());
}
}
}
/**
* See {@link android.webkit.WebSettings#getBuiltInZoomControls}.
*/
public boolean getBuiltInZoomControls() {
synchronized (mAwSettingsLock) {
return mBuiltInZoomControls;
}
}
/**
* See {@link android.webkit.WebSettings#setDisplayZoomControls}.
*/
public void setDisplayZoomControls(boolean enabled) {
synchronized (mAwSettingsLock) {
mDisplayZoomControls = enabled;
}
}
/**
* See {@link android.webkit.WebSettings#getDisplayZoomControls}.
*/
public boolean getDisplayZoomControls() {
synchronized (mAwSettingsLock) {
return mDisplayZoomControls;
}
}
@CalledByNative
private boolean supportsDoubleTapZoomLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mSupportZoom && mBuiltInZoomControls && mUseWideViewport;
}
private boolean supportsMultiTouchZoomLocked() {
assert Thread.holdsLock(mAwSettingsLock);
return mSupportZoom && mBuiltInZoomControls;
}
boolean supportsMultiTouchZoom() {
synchronized (mAwSettingsLock) {
return supportsMultiTouchZoomLocked();
}
}
boolean shouldDisplayZoomControls() {
synchronized (mAwSettingsLock) {
return supportsMultiTouchZoomLocked() && mDisplayZoomControls;
}
}
private int clipFontSize(int size) {
if (size < MINIMUM_FONT_SIZE) {
return MINIMUM_FONT_SIZE;
} else if (size > MAXIMUM_FONT_SIZE) {
return MAXIMUM_FONT_SIZE;
}
return size;
}
@CalledByNative
private void updateEverything() {
synchronized (mAwSettingsLock) {
nativeUpdateEverythingLocked(mNativeAwSettings);
}
}
@CalledByNative
private void populateWebPreferences(long webPrefsPtr) {
synchronized (mAwSettingsLock) {
nativePopulateWebPreferencesLocked(mNativeAwSettings, webPrefsPtr);
}
}
private void updateWebkitPreferencesOnUiThreadLocked() {
assert mEventHandler.mHandler != null;
ThreadUtils.assertOnUiThread();
nativeUpdateWebkitPreferencesLocked(mNativeAwSettings);
}
private native long nativeInit(long webContentsPtr);
private native void nativeDestroy(long nativeAwSettings);
private native void nativePopulateWebPreferencesLocked(long nativeAwSettings, long webPrefsPtr);
private native void nativeResetScrollAndScaleState(long nativeAwSettings);
private native void nativeUpdateEverythingLocked(long nativeAwSettings);
private native void nativeUpdateInitialPageScaleLocked(long nativeAwSettings);
private native void nativeUpdateUserAgentLocked(long nativeAwSettings);
private native void nativeUpdateWebkitPreferencesLocked(long nativeAwSettings);
private static native String nativeGetDefaultUserAgent();
private native void nativeUpdateFormDataPreferencesLocked(long nativeAwSettings);
}