WebSettingsClassic.java revision 524c878e7ee8aba1a4e1be0d2cc76ef42e8fcda1
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
19import android.content.Context;
20import android.content.SharedPreferences;
21import android.content.pm.PackageManager;
22import android.os.Build;
23import android.os.Handler;
24import android.os.Message;
25import android.provider.Settings;
26import android.provider.Settings.SettingNotFoundException;
27import android.util.EventLog;
28
29import java.util.Locale;
30
31/**
32 * WebSettings implementation for the WebViewClassic implementation of WebView.
33 * @hide
34 */
35public class WebSettingsClassic extends WebSettings {
36    // TODO: Keep this up to date
37    private static final String PREVIOUS_VERSION = "4.1.1";
38
39    // WebView associated with this WebSettings.
40    private WebViewClassic mWebView;
41    // BrowserFrame used to access the native frame pointer.
42    private BrowserFrame mBrowserFrame;
43    // Flag to prevent multiple SYNC messages at one time.
44    private boolean mSyncPending = false;
45    // Custom handler that queues messages until the WebCore thread is active.
46    private final EventHandler mEventHandler;
47
48    // Private settings so we don't have to go into native code to
49    // retrieve the values. After setXXX, postSync() needs to be called.
50    //
51    // The default values need to match those in WebSettings.cpp
52    // If the defaults change, please also update the JavaDocs so developers
53    // know what they are.
54    private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
55    private Context         mContext;
56    private int             mTextSize = 100;
57    private String          mStandardFontFamily = "sans-serif";
58    private String          mFixedFontFamily = "monospace";
59    private String          mSansSerifFontFamily = "sans-serif";
60    private String          mSerifFontFamily = "serif";
61    private String          mCursiveFontFamily = "cursive";
62    private String          mFantasyFontFamily = "fantasy";
63    private String          mDefaultTextEncoding;
64    private String          mUserAgent;
65    private boolean         mUseDefaultUserAgent;
66    private String          mAcceptLanguage;
67    private int             mMinimumFontSize = 8;
68    private int             mMinimumLogicalFontSize = 8;
69    private int             mDefaultFontSize = 16;
70    private int             mDefaultFixedFontSize = 13;
71    private int             mPageCacheCapacity = 0;
72    private boolean         mLoadsImagesAutomatically = true;
73    private boolean         mBlockNetworkImage = false;
74    private boolean         mBlockNetworkLoads;
75    private boolean         mJavaScriptEnabled = false;
76    private boolean         mAllowUniversalAccessFromFileURLs = false;
77    private boolean         mAllowFileAccessFromFileURLs = false;
78    private boolean         mHardwareAccelSkia = false;
79    private boolean         mShowVisualIndicator = false;
80    private PluginState     mPluginState = PluginState.OFF;
81    private boolean         mJavaScriptCanOpenWindowsAutomatically = false;
82    private boolean         mUseDoubleTree = false;
83    private boolean         mUseWideViewport = false;
84    private boolean         mSupportMultipleWindows = false;
85    private boolean         mShrinksStandaloneImagesToFit = false;
86    private long            mMaximumDecodedImageSize = 0; // 0 means default
87    private boolean         mPrivateBrowsingEnabled = false;
88    private boolean         mSyntheticLinksEnabled = true;
89    // HTML5 API flags
90    private boolean         mAppCacheEnabled = false;
91    private boolean         mDatabaseEnabled = false;
92    private boolean         mDomStorageEnabled = false;
93    private boolean         mWorkersEnabled = false;  // only affects V8.
94    private boolean         mGeolocationEnabled = true;
95    private boolean         mXSSAuditorEnabled = false;
96    private boolean         mLinkPrefetchEnabled = false;
97    // HTML5 configuration parameters
98    private long            mAppCacheMaxSize = Long.MAX_VALUE;
99    private String          mAppCachePath = null;
100    private String          mDatabasePath = "";
101    // The WebCore DatabaseTracker only allows the database path to be set
102    // once. Keep track of when the path has been set.
103    private boolean         mDatabasePathHasBeenSet = false;
104    private String          mGeolocationDatabasePath = "";
105    // Don't need to synchronize the get/set methods as they
106    // are basic types, also none of these values are used in
107    // native WebCore code.
108    private ZoomDensity     mDefaultZoom = ZoomDensity.MEDIUM;
109    private RenderPriority  mRenderPriority = RenderPriority.NORMAL;
110    private int             mOverrideCacheMode = LOAD_DEFAULT;
111    private int             mDoubleTapZoom = 100;
112    private boolean         mSaveFormData = true;
113    private boolean         mAutoFillEnabled = false;
114    private boolean         mSavePassword = true;
115    private boolean         mLightTouchEnabled = false;
116    private boolean         mNeedInitialFocus = true;
117    private boolean         mNavDump = false;
118    private boolean         mSupportZoom = true;
119    private boolean         mMediaPlaybackRequiresUserGesture = true;
120    private boolean         mBuiltInZoomControls = false;
121    private boolean         mDisplayZoomControls = true;
122    private boolean         mAllowFileAccess = true;
123    private boolean         mAllowContentAccess = true;
124    private boolean         mLoadWithOverviewMode = false;
125    private boolean         mEnableSmoothTransition = false;
126    private boolean         mForceUserScalable = false;
127    private boolean         mPasswordEchoEnabled = true;
128
129    // AutoFill Profile data
130    public static class AutoFillProfile {
131        private int mUniqueId;
132        private String mFullName;
133        private String mEmailAddress;
134        private String mCompanyName;
135        private String mAddressLine1;
136        private String mAddressLine2;
137        private String mCity;
138        private String mState;
139        private String mZipCode;
140        private String mCountry;
141        private String mPhoneNumber;
142
143        public AutoFillProfile(int uniqueId, String fullName, String email,
144                String companyName, String addressLine1, String addressLine2,
145                String city, String state, String zipCode, String country,
146                String phoneNumber) {
147            mUniqueId = uniqueId;
148            mFullName = fullName;
149            mEmailAddress = email;
150            mCompanyName = companyName;
151            mAddressLine1 = addressLine1;
152            mAddressLine2 = addressLine2;
153            mCity = city;
154            mState = state;
155            mZipCode = zipCode;
156            mCountry = country;
157            mPhoneNumber = phoneNumber;
158        }
159
160        public int getUniqueId() { return mUniqueId; }
161        public String getFullName() { return mFullName; }
162        public String getEmailAddress() { return mEmailAddress; }
163        public String getCompanyName() { return mCompanyName; }
164        public String getAddressLine1() { return mAddressLine1; }
165        public String getAddressLine2() { return mAddressLine2; }
166        public String getCity() { return mCity; }
167        public String getState() { return mState; }
168        public String getZipCode() { return mZipCode; }
169        public String getCountry() { return mCountry; }
170        public String getPhoneNumber() { return mPhoneNumber; }
171    }
172
173
174    private AutoFillProfile mAutoFillProfile;
175
176    private boolean         mUseWebViewBackgroundForOverscroll = true;
177
178    // private WebSettings, not accessible by the host activity
179    static private int      mDoubleTapToastCount = 3;
180
181    private static final String PREF_FILE = "WebViewSettings";
182    private static final String DOUBLE_TAP_TOAST_COUNT = "double_tap_toast_count";
183
184    // Class to handle messages before WebCore is ready.
185    private class EventHandler {
186        // Message id for syncing
187        static final int SYNC = 0;
188        // Message id for setting priority
189        static final int PRIORITY = 1;
190        // Message id for writing double-tap toast count
191        static final int SET_DOUBLE_TAP_TOAST_COUNT = 2;
192        // Actual WebCore thread handler
193        private Handler mHandler;
194
195        private synchronized void createHandler() {
196            // as mRenderPriority can be set before thread is running, sync up
197            setRenderPriority();
198
199            // create a new handler
200            mHandler = new Handler() {
201                @Override
202                public void handleMessage(Message msg) {
203                    switch (msg.what) {
204                        case SYNC:
205                            synchronized (WebSettingsClassic.this) {
206                                if (mBrowserFrame.mNativeFrame != 0) {
207                                    nativeSync(mBrowserFrame.mNativeFrame);
208                                }
209                                mSyncPending = false;
210                            }
211                            break;
212
213                        case PRIORITY: {
214                            setRenderPriority();
215                            break;
216                        }
217
218                        case SET_DOUBLE_TAP_TOAST_COUNT: {
219                            SharedPreferences.Editor editor = mContext
220                                    .getSharedPreferences(PREF_FILE,
221                                            Context.MODE_PRIVATE).edit();
222                            editor.putInt(DOUBLE_TAP_TOAST_COUNT,
223                                    mDoubleTapToastCount);
224                            editor.commit();
225                            break;
226                        }
227                    }
228                }
229            };
230        }
231
232        private void setRenderPriority() {
233            synchronized (WebSettingsClassic.this) {
234                if (mRenderPriority == RenderPriority.NORMAL) {
235                    android.os.Process.setThreadPriority(
236                            android.os.Process.THREAD_PRIORITY_DEFAULT);
237                } else if (mRenderPriority == RenderPriority.HIGH) {
238                    android.os.Process.setThreadPriority(
239                            android.os.Process.THREAD_PRIORITY_FOREGROUND +
240                            android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
241                } else if (mRenderPriority == RenderPriority.LOW) {
242                    android.os.Process.setThreadPriority(
243                            android.os.Process.THREAD_PRIORITY_BACKGROUND);
244                }
245            }
246        }
247
248        /**
249         * Send a message to the private queue or handler.
250         */
251        private synchronized boolean sendMessage(Message msg) {
252            if (mHandler != null) {
253                mHandler.sendMessage(msg);
254                return true;
255            } else {
256                return false;
257            }
258        }
259    }
260
261    // User agent strings.
262    private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (X11; " +
263        "Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) " +
264        "Chrome/11.0.696.34 Safari/534.24";
265    private static final String IPHONE_USERAGENT =
266            "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)"
267            + " AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0"
268            + " Mobile/7A341 Safari/528.16";
269    private static Locale sLocale;
270    private static Object sLockForLocaleSettings;
271
272    /**
273     * Package constructor to prevent clients from creating a new settings
274     * instance.
275     */
276    WebSettingsClassic(Context context, WebViewClassic webview) {
277        mEventHandler = new EventHandler();
278        mContext = context;
279        mWebView = webview;
280        mDefaultTextEncoding = context.getString(com.android.internal.
281                                                 R.string.default_text_encoding);
282
283        if (sLockForLocaleSettings == null) {
284            sLockForLocaleSettings = new Object();
285            sLocale = Locale.getDefault();
286        }
287        mAcceptLanguage = getCurrentAcceptLanguage();
288        mUserAgent = getCurrentUserAgent();
289        mUseDefaultUserAgent = true;
290
291        mBlockNetworkLoads = mContext.checkPermission(
292                "android.permission.INTERNET", android.os.Process.myPid(),
293                android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED;
294
295        // SDK specific settings. See issue 6212665
296        if (mContext.getApplicationInfo().targetSdkVersion <
297                Build.VERSION_CODES.JELLY_BEAN) {
298            mAllowUniversalAccessFromFileURLs = true;
299            mAllowFileAccessFromFileURLs = true;
300        }
301        try {
302            mPasswordEchoEnabled =
303                    Settings.System.getInt(context.getContentResolver(),
304                        Settings.System.TEXT_SHOW_PASSWORD) != 0;
305        } catch (SettingNotFoundException e) {
306            mPasswordEchoEnabled = true;
307        }
308    }
309
310    private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";
311
312    /**
313     * Looks at sLocale and returns current AcceptLanguage String.
314     * @return Current AcceptLanguage String.
315     */
316    private String getCurrentAcceptLanguage() {
317        Locale locale;
318        synchronized(sLockForLocaleSettings) {
319            locale = sLocale;
320        }
321        StringBuilder buffer = new StringBuilder();
322        addLocaleToHttpAcceptLanguage(buffer, locale);
323
324        if (!Locale.US.equals(locale)) {
325            if (buffer.length() > 0) {
326                buffer.append(", ");
327            }
328            buffer.append(ACCEPT_LANG_FOR_US_LOCALE);
329        }
330
331        return buffer.toString();
332    }
333
334    /**
335     * Convert obsolete language codes, including Hebrew/Indonesian/Yiddish,
336     * to new standard.
337     */
338    private static String convertObsoleteLanguageCodeToNew(String langCode) {
339        if (langCode == null) {
340            return null;
341        }
342        if ("iw".equals(langCode)) {
343            // Hebrew
344            return "he";
345        } else if ("in".equals(langCode)) {
346            // Indonesian
347            return "id";
348        } else if ("ji".equals(langCode)) {
349            // Yiddish
350            return "yi";
351        }
352        return langCode;
353    }
354
355    private static void addLocaleToHttpAcceptLanguage(StringBuilder builder,
356                                                      Locale locale) {
357        String language = convertObsoleteLanguageCodeToNew(locale.getLanguage());
358        if (language != null) {
359            builder.append(language);
360            String country = locale.getCountry();
361            if (country != null) {
362                builder.append("-");
363                builder.append(country);
364            }
365        }
366    }
367
368    /**
369     * Looks at sLocale and mContext and returns current UserAgent String.
370     * @return Current UserAgent String.
371     */
372    private synchronized String getCurrentUserAgent() {
373        Locale locale;
374        synchronized(sLockForLocaleSettings) {
375            locale = sLocale;
376        }
377        StringBuffer buffer = new StringBuffer();
378        // Add version
379        final String version = Build.VERSION.RELEASE;
380        if (version.length() > 0) {
381            if (Character.isDigit(version.charAt(0))) {
382                // Release is a version, eg "3.1"
383                buffer.append(version);
384            } else {
385                // Release is a codename, eg "Honeycomb"
386                // In this case, use the previous release's version
387                buffer.append(PREVIOUS_VERSION);
388            }
389        } else {
390            // default to "1.0"
391            buffer.append("1.0");
392        }
393        buffer.append("; ");
394        final String language = locale.getLanguage();
395        if (language != null) {
396            buffer.append(convertObsoleteLanguageCodeToNew(language));
397            final String country = locale.getCountry();
398            if (country != null) {
399                buffer.append("-");
400                buffer.append(country.toLowerCase());
401            }
402        } else {
403            // default to "en"
404            buffer.append("en");
405        }
406        buffer.append(";");
407        // add the model for the release build
408        if ("REL".equals(Build.VERSION.CODENAME)) {
409            final String model = Build.MODEL;
410            if (model.length() > 0) {
411                buffer.append(" ");
412                buffer.append(model);
413            }
414        }
415        final String id = Build.ID;
416        if (id.length() > 0) {
417            buffer.append(" Build/");
418            buffer.append(id);
419        }
420        String mobile = mContext.getResources().getText(
421            com.android.internal.R.string.web_user_agent_target_content).toString();
422        final String base = mContext.getResources().getText(
423                com.android.internal.R.string.web_user_agent).toString();
424        return String.format(base, buffer, mobile);
425    }
426
427    /**
428     * @see android.webkit.WebSettings#setNavDump(boolean)
429     */
430    @Override
431    @Deprecated
432    public void setNavDump(boolean enabled) {
433        mNavDump = enabled;
434    }
435
436    /**
437     * @see android.webkit.WebSettings#getNavDump()
438     */
439    @Override
440    @Deprecated
441    public boolean getNavDump() {
442        return mNavDump;
443    }
444
445    /**
446     * @see android.webkit.WebSettings#setSupportZoom(boolean)
447     */
448    @Override
449    public void setSupportZoom(boolean support) {
450        mSupportZoom = support;
451        mWebView.updateMultiTouchSupport(mContext);
452    }
453
454    /**
455     * @see android.webkit.WebSettings#supportZoom()
456     */
457    @Override
458    public boolean supportZoom() {
459        return mSupportZoom;
460    }
461
462    /**
463     * @see android.webkit.WebSettings#setMediaPlaybackRequiresUserGesture(boolean)
464     */
465    @Override
466    public void setMediaPlaybackRequiresUserGesture(boolean support) {
467        if (mMediaPlaybackRequiresUserGesture != support) {
468            mMediaPlaybackRequiresUserGesture = support;
469            postSync();
470        }
471    }
472
473    /**
474     * @see android.webkit.WebSettings#getMediaPlaybackRequiresUserGesture()
475     */
476    @Override
477    public boolean getMediaPlaybackRequiresUserGesture() {
478        return mMediaPlaybackRequiresUserGesture;
479    }
480
481    /**
482     * @see android.webkit.WebSettings#setBuiltInZoomControls(boolean)
483     */
484    @Override
485    public void setBuiltInZoomControls(boolean enabled) {
486        mBuiltInZoomControls = enabled;
487        mWebView.updateMultiTouchSupport(mContext);
488    }
489
490    /**
491     * @see android.webkit.WebSettings#getBuiltInZoomControls()
492     */
493    @Override
494    public boolean getBuiltInZoomControls() {
495        return mBuiltInZoomControls;
496    }
497
498    /**
499     * @see android.webkit.WebSettings#setDisplayZoomControls(boolean)
500     */
501    @Override
502    public void setDisplayZoomControls(boolean enabled) {
503        mDisplayZoomControls = enabled;
504        mWebView.updateMultiTouchSupport(mContext);
505    }
506
507    /**
508     * @see android.webkit.WebSettings#getDisplayZoomControls()
509     */
510    @Override
511    public boolean getDisplayZoomControls() {
512        return mDisplayZoomControls;
513    }
514
515    /**
516     * @see android.webkit.WebSettings#setAllowFileAccess(boolean)
517     */
518    @Override
519    public void setAllowFileAccess(boolean allow) {
520        mAllowFileAccess = allow;
521    }
522
523    /**
524     * @see android.webkit.WebSettings#getAllowFileAccess()
525     */
526    @Override
527    public boolean getAllowFileAccess() {
528        return mAllowFileAccess;
529    }
530
531    /**
532     * @see android.webkit.WebSettings#setAllowContentAccess(boolean)
533     */
534    @Override
535    public void setAllowContentAccess(boolean allow) {
536        mAllowContentAccess = allow;
537    }
538
539    /**
540     * @see android.webkit.WebSettings#getAllowContentAccess()
541     */
542    @Override
543    public boolean getAllowContentAccess() {
544        return mAllowContentAccess;
545    }
546
547    /**
548     * @see android.webkit.WebSettings#setLoadWithOverviewMode(boolean)
549     */
550    @Override
551    public void setLoadWithOverviewMode(boolean overview) {
552        mLoadWithOverviewMode = overview;
553    }
554
555    /**
556     * @see android.webkit.WebSettings#getLoadWithOverviewMode()
557     */
558    @Override
559    public boolean getLoadWithOverviewMode() {
560        return mLoadWithOverviewMode;
561    }
562
563    /**
564     * @see android.webkit.WebSettings#setEnableSmoothTransition(boolean)
565     */
566    @Override
567    public void setEnableSmoothTransition(boolean enable) {
568        mEnableSmoothTransition = enable;
569    }
570
571    /**
572     * @see android.webkit.WebSettings#enableSmoothTransition()
573     */
574    @Override
575    public boolean enableSmoothTransition() {
576        return mEnableSmoothTransition;
577    }
578
579    /**
580     * @see android.webkit.WebSettings#setUseWebViewBackgroundForOverscrollBackground(boolean)
581     */
582    @Override
583    @Deprecated
584    public void setUseWebViewBackgroundForOverscrollBackground(boolean view) {
585        mUseWebViewBackgroundForOverscroll = view;
586    }
587
588    /**
589     * @see android.webkit.WebSettings#getUseWebViewBackgroundForOverscrollBackground()
590     */
591    @Override
592    @Deprecated
593    public boolean getUseWebViewBackgroundForOverscrollBackground() {
594        return mUseWebViewBackgroundForOverscroll;
595    }
596
597    /**
598     * @see android.webkit.WebSettings#setSaveFormData(boolean)
599     */
600    @Override
601    public void setSaveFormData(boolean save) {
602        mSaveFormData = save;
603    }
604
605    /**
606     * @see android.webkit.WebSettings#getSaveFormData()
607     */
608    @Override
609    public boolean getSaveFormData() {
610        return mSaveFormData && !mPrivateBrowsingEnabled;
611    }
612
613    /**
614     * @see android.webkit.WebSettings#setSavePassword(boolean)
615     */
616    @Override
617    public void setSavePassword(boolean save) {
618        mSavePassword = save;
619    }
620
621    /**
622     * @see android.webkit.WebSettings#getSavePassword()
623     */
624    @Override
625    public boolean getSavePassword() {
626        return mSavePassword;
627    }
628
629    /**
630     * @see android.webkit.WebSettings#setTextZoom(int)
631     */
632    @Override
633    public synchronized void setTextZoom(int textZoom) {
634        if (mTextSize != textZoom) {
635            if (WebViewClassic.mLogEvent) {
636                EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE,
637                        mTextSize, textZoom);
638            }
639            mTextSize = textZoom;
640            postSync();
641        }
642    }
643
644    /**
645     * @see android.webkit.WebSettings#getTextZoom()
646     */
647    @Override
648    public synchronized int getTextZoom() {
649        return mTextSize;
650    }
651
652    /**
653     * @see android.webkit.WebSettings#setTextSize(android.webkit.WebSettingsClassic.TextSize)
654     */
655    @Override
656    public synchronized void setTextSize(TextSize t) {
657        setTextZoom(t.value);
658    }
659
660    /**
661     * @see android.webkit.WebSettings#getTextSize()
662     */
663    @Override
664    public synchronized TextSize getTextSize() {
665        TextSize closestSize = null;
666        int smallestDelta = Integer.MAX_VALUE;
667        for (TextSize size : TextSize.values()) {
668            int delta = Math.abs(mTextSize - size.value);
669            if (delta == 0) {
670                return size;
671            }
672            if (delta < smallestDelta) {
673                smallestDelta = delta;
674                closestSize = size;
675            }
676        }
677        return closestSize != null ? closestSize : TextSize.NORMAL;
678    }
679
680    /**
681     * Set the double-tap zoom of the page in percent. Default is 100.
682     * @param doubleTapZoom A percent value for increasing or decreasing the double-tap zoom.
683     */
684    public void setDoubleTapZoom(int doubleTapZoom) {
685        if (mDoubleTapZoom != doubleTapZoom) {
686            mDoubleTapZoom = doubleTapZoom;
687            mWebView.updateDoubleTapZoom(doubleTapZoom);
688        }
689    }
690
691    /**
692     * Get the double-tap zoom of the page in percent.
693     * @return A percent value describing the double-tap zoom.
694     */
695    public int getDoubleTapZoom() {
696        return mDoubleTapZoom;
697    }
698
699    /**
700     * @see android.webkit.WebSettings#setDefaultZoom(android.webkit.WebSettingsClassic.ZoomDensity)
701     */
702    @Override
703    public void setDefaultZoom(ZoomDensity zoom) {
704        if (mDefaultZoom != zoom) {
705            mDefaultZoom = zoom;
706            mWebView.adjustDefaultZoomDensity(zoom.value);
707        }
708    }
709
710    /**
711     * @see android.webkit.WebSettings#getDefaultZoom()
712     */
713    @Override
714    public ZoomDensity getDefaultZoom() {
715        return mDefaultZoom;
716    }
717
718    /**
719     * @see android.webkit.WebSettings#setLightTouchEnabled(boolean)
720     */
721    @Override
722    public void setLightTouchEnabled(boolean enabled) {
723        mLightTouchEnabled = enabled;
724    }
725
726    /**
727     * @see android.webkit.WebSettings#getLightTouchEnabled()
728     */
729    @Override
730    public boolean getLightTouchEnabled() {
731        return mLightTouchEnabled;
732    }
733
734    /**
735     * @see android.webkit.WebSettings#setUseDoubleTree(boolean)
736     */
737    @Override
738    @Deprecated
739    public synchronized void setUseDoubleTree(boolean use) {
740        return;
741    }
742
743    /**
744     * @see android.webkit.WebSettings#getUseDoubleTree()
745     */
746    @Override
747    @Deprecated
748    public synchronized boolean getUseDoubleTree() {
749        return false;
750    }
751
752    /**
753     * @see android.webkit.WebSettings#setUserAgent(int)
754     */
755    @Override
756    @Deprecated
757    public synchronized void setUserAgent(int ua) {
758        String uaString = null;
759        if (ua == 1) {
760            if (DESKTOP_USERAGENT.equals(mUserAgent)) {
761                return; // do nothing
762            } else {
763                uaString = DESKTOP_USERAGENT;
764            }
765        } else if (ua == 2) {
766            if (IPHONE_USERAGENT.equals(mUserAgent)) {
767                return; // do nothing
768            } else {
769                uaString = IPHONE_USERAGENT;
770            }
771        } else if (ua != 0) {
772            return; // do nothing
773        }
774        setUserAgentString(uaString);
775    }
776
777    /**
778     * @see android.webkit.WebSettings#getUserAgent()
779     */
780    @Override
781    @Deprecated
782    public synchronized int getUserAgent() {
783        if (DESKTOP_USERAGENT.equals(mUserAgent)) {
784            return 1;
785        } else if (IPHONE_USERAGENT.equals(mUserAgent)) {
786            return 2;
787        } else if (mUseDefaultUserAgent) {
788            return 0;
789        }
790        return -1;
791    }
792
793    /**
794     * @see android.webkit.WebSettings#setUseWideViewPort(boolean)
795     */
796    @Override
797    public synchronized void setUseWideViewPort(boolean use) {
798        if (mUseWideViewport != use) {
799            mUseWideViewport = use;
800            postSync();
801        }
802    }
803
804    /**
805     * @see android.webkit.WebSettings#getUseWideViewPort()
806     */
807    @Override
808    public synchronized boolean getUseWideViewPort() {
809        return mUseWideViewport;
810    }
811
812    /**
813     * @see android.webkit.WebSettings#setSupportMultipleWindows(boolean)
814     */
815    @Override
816    public synchronized void setSupportMultipleWindows(boolean support) {
817        if (mSupportMultipleWindows != support) {
818            mSupportMultipleWindows = support;
819            postSync();
820        }
821    }
822
823    /**
824     * @see android.webkit.WebSettings#supportMultipleWindows()
825     */
826    @Override
827    public synchronized boolean supportMultipleWindows() {
828        return mSupportMultipleWindows;
829    }
830
831    /**
832     * @see android.webkit.WebSettings#setLayoutAlgorithm(android.webkit.WebSettingsClassic.LayoutAlgorithm)
833     */
834    @Override
835    public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
836        // XXX: This will only be affective if libwebcore was built with
837        // ANDROID_LAYOUT defined.
838        if (mLayoutAlgorithm != l) {
839            mLayoutAlgorithm = l;
840            postSync();
841        }
842    }
843
844    /**
845     * @see android.webkit.WebSettings#getLayoutAlgorithm()
846     */
847    @Override
848    public synchronized LayoutAlgorithm getLayoutAlgorithm() {
849        return mLayoutAlgorithm;
850    }
851
852    /**
853     * @see android.webkit.WebSettings#setStandardFontFamily(java.lang.String)
854     */
855    @Override
856    public synchronized void setStandardFontFamily(String font) {
857        if (font != null && !font.equals(mStandardFontFamily)) {
858            mStandardFontFamily = font;
859            postSync();
860        }
861    }
862
863    /**
864     * @see android.webkit.WebSettings#getStandardFontFamily()
865     */
866    @Override
867    public synchronized String getStandardFontFamily() {
868        return mStandardFontFamily;
869    }
870
871    /**
872     * @see android.webkit.WebSettings#setFixedFontFamily(java.lang.String)
873     */
874    @Override
875    public synchronized void setFixedFontFamily(String font) {
876        if (font != null && !font.equals(mFixedFontFamily)) {
877            mFixedFontFamily = font;
878            postSync();
879        }
880    }
881
882    /**
883     * @see android.webkit.WebSettings#getFixedFontFamily()
884     */
885    @Override
886    public synchronized String getFixedFontFamily() {
887        return mFixedFontFamily;
888    }
889
890    /**
891     * @see android.webkit.WebSettings#setSansSerifFontFamily(java.lang.String)
892     */
893    @Override
894    public synchronized void setSansSerifFontFamily(String font) {
895        if (font != null && !font.equals(mSansSerifFontFamily)) {
896            mSansSerifFontFamily = font;
897            postSync();
898        }
899    }
900
901    /**
902     * @see android.webkit.WebSettings#getSansSerifFontFamily()
903     */
904    @Override
905    public synchronized String getSansSerifFontFamily() {
906        return mSansSerifFontFamily;
907    }
908
909    /**
910     * @see android.webkit.WebSettings#setSerifFontFamily(java.lang.String)
911     */
912    @Override
913    public synchronized void setSerifFontFamily(String font) {
914        if (font != null && !font.equals(mSerifFontFamily)) {
915            mSerifFontFamily = font;
916            postSync();
917        }
918    }
919
920    /**
921     * @see android.webkit.WebSettings#getSerifFontFamily()
922     */
923    @Override
924    public synchronized String getSerifFontFamily() {
925        return mSerifFontFamily;
926    }
927
928    /**
929     * @see android.webkit.WebSettings#setCursiveFontFamily(java.lang.String)
930     */
931    @Override
932    public synchronized void setCursiveFontFamily(String font) {
933        if (font != null && !font.equals(mCursiveFontFamily)) {
934            mCursiveFontFamily = font;
935            postSync();
936        }
937    }
938
939    /**
940     * @see android.webkit.WebSettings#getCursiveFontFamily()
941     */
942    @Override
943    public synchronized String getCursiveFontFamily() {
944        return mCursiveFontFamily;
945    }
946
947    /**
948     * @see android.webkit.WebSettings#setFantasyFontFamily(java.lang.String)
949     */
950    @Override
951    public synchronized void setFantasyFontFamily(String font) {
952        if (font != null && !font.equals(mFantasyFontFamily)) {
953            mFantasyFontFamily = font;
954            postSync();
955        }
956    }
957
958    /**
959     * @see android.webkit.WebSettings#getFantasyFontFamily()
960     */
961    @Override
962    public synchronized String getFantasyFontFamily() {
963        return mFantasyFontFamily;
964    }
965
966    /**
967     * @see android.webkit.WebSettings#setMinimumFontSize(int)
968     */
969    @Override
970    public synchronized void setMinimumFontSize(int size) {
971        size = pin(size);
972        if (mMinimumFontSize != size) {
973            mMinimumFontSize = size;
974            postSync();
975        }
976    }
977
978    /**
979     * @see android.webkit.WebSettings#getMinimumFontSize()
980     */
981    @Override
982    public synchronized int getMinimumFontSize() {
983        return mMinimumFontSize;
984    }
985
986    /**
987     * @see android.webkit.WebSettings#setMinimumLogicalFontSize(int)
988     */
989    @Override
990    public synchronized void setMinimumLogicalFontSize(int size) {
991        size = pin(size);
992        if (mMinimumLogicalFontSize != size) {
993            mMinimumLogicalFontSize = size;
994            postSync();
995        }
996    }
997
998    /**
999     * @see android.webkit.WebSettings#getMinimumLogicalFontSize()
1000     */
1001    @Override
1002    public synchronized int getMinimumLogicalFontSize() {
1003        return mMinimumLogicalFontSize;
1004    }
1005
1006    /**
1007     * @see android.webkit.WebSettings#setDefaultFontSize(int)
1008     */
1009    @Override
1010    public synchronized void setDefaultFontSize(int size) {
1011        size = pin(size);
1012        if (mDefaultFontSize != size) {
1013            mDefaultFontSize = size;
1014            postSync();
1015        }
1016    }
1017
1018    /**
1019     * @see android.webkit.WebSettings#getDefaultFontSize()
1020     */
1021    @Override
1022    public synchronized int getDefaultFontSize() {
1023        return mDefaultFontSize;
1024    }
1025
1026    /**
1027     * @see android.webkit.WebSettings#setDefaultFixedFontSize(int)
1028     */
1029    @Override
1030    public synchronized void setDefaultFixedFontSize(int size) {
1031        size = pin(size);
1032        if (mDefaultFixedFontSize != size) {
1033            mDefaultFixedFontSize = size;
1034            postSync();
1035        }
1036    }
1037
1038    /**
1039     * @see android.webkit.WebSettings#getDefaultFixedFontSize()
1040     */
1041    @Override
1042    public synchronized int getDefaultFixedFontSize() {
1043        return mDefaultFixedFontSize;
1044    }
1045
1046    /**
1047     * Set the number of pages cached by the WebKit for the history navigation.
1048     * @param size A non-negative integer between 0 (no cache) and 20 (max).
1049     */
1050    public synchronized void setPageCacheCapacity(int size) {
1051        if (size < 0) size = 0;
1052        if (size > 20) size = 20;
1053        if (mPageCacheCapacity != size) {
1054            mPageCacheCapacity = size;
1055            postSync();
1056        }
1057    }
1058
1059    /**
1060     * @see android.webkit.WebSettings#setLoadsImagesAutomatically(boolean)
1061     */
1062    @Override
1063    public synchronized void setLoadsImagesAutomatically(boolean flag) {
1064        if (mLoadsImagesAutomatically != flag) {
1065            mLoadsImagesAutomatically = flag;
1066            postSync();
1067        }
1068    }
1069
1070    /**
1071     * @see android.webkit.WebSettings#getLoadsImagesAutomatically()
1072     */
1073    @Override
1074    public synchronized boolean getLoadsImagesAutomatically() {
1075        return mLoadsImagesAutomatically;
1076    }
1077
1078    /**
1079     * @see android.webkit.WebSettings#setBlockNetworkImage(boolean)
1080     */
1081    @Override
1082    public synchronized void setBlockNetworkImage(boolean flag) {
1083        if (mBlockNetworkImage != flag) {
1084            mBlockNetworkImage = flag;
1085            postSync();
1086        }
1087    }
1088
1089    /**
1090     * @see android.webkit.WebSettings#getBlockNetworkImage()
1091     */
1092    @Override
1093    public synchronized boolean getBlockNetworkImage() {
1094        return mBlockNetworkImage;
1095    }
1096
1097    /**
1098     * @see android.webkit.WebSettings#setBlockNetworkLoads(boolean)
1099     */
1100    @Override
1101    public synchronized void setBlockNetworkLoads(boolean flag) {
1102        if (mBlockNetworkLoads != flag) {
1103            mBlockNetworkLoads = flag;
1104            verifyNetworkAccess();
1105            postSync();
1106        }
1107    }
1108
1109    /**
1110     * @see android.webkit.WebSettings#getBlockNetworkLoads()
1111     */
1112    @Override
1113    public synchronized boolean getBlockNetworkLoads() {
1114        return mBlockNetworkLoads;
1115    }
1116
1117
1118    private void verifyNetworkAccess() {
1119        if (!mBlockNetworkLoads) {
1120            if (mContext.checkPermission("android.permission.INTERNET",
1121                    android.os.Process.myPid(), android.os.Process.myUid()) !=
1122                        PackageManager.PERMISSION_GRANTED) {
1123                throw new SecurityException
1124                        ("Permission denied - " +
1125                                "application missing INTERNET permission");
1126            }
1127        }
1128    }
1129
1130    /**
1131     * @see android.webkit.WebSettings#setJavaScriptEnabled(boolean)
1132     */
1133    @Override
1134    public synchronized void setJavaScriptEnabled(boolean flag) {
1135        if (mJavaScriptEnabled != flag) {
1136            mJavaScriptEnabled = flag;
1137            postSync();
1138        }
1139    }
1140
1141    /**
1142     * @see android.webkit.WebSettings#setAllowUniversalAccessFromFileURLs
1143     */
1144    @Override
1145    public synchronized void setAllowUniversalAccessFromFileURLs(boolean flag) {
1146        if (mAllowUniversalAccessFromFileURLs != flag) {
1147            mAllowUniversalAccessFromFileURLs = flag;
1148            postSync();
1149        }
1150    }
1151
1152    /**
1153     * @see android.webkit.WebSettings#setAllowFileAccessFromFileURLs
1154     */
1155    @Override
1156    public synchronized void setAllowFileAccessFromFileURLs(boolean flag) {
1157        if (mAllowFileAccessFromFileURLs != flag) {
1158            mAllowFileAccessFromFileURLs = flag;
1159            postSync();
1160        }
1161    }
1162
1163    /**
1164     * Tell the WebView to use Skia's hardware accelerated rendering path
1165     * @param flag True if the WebView should use Skia's hw-accel path
1166     */
1167    public synchronized void setHardwareAccelSkiaEnabled(boolean flag) {
1168        if (mHardwareAccelSkia != flag) {
1169            mHardwareAccelSkia = flag;
1170            postSync();
1171        }
1172    }
1173
1174    /**
1175     * @return True if the WebView is using hardware accelerated skia
1176     */
1177    public synchronized boolean getHardwareAccelSkiaEnabled() {
1178        return mHardwareAccelSkia;
1179    }
1180
1181    /**
1182     * Tell the WebView to show the visual indicator
1183     * @param flag True if the WebView should show the visual indicator
1184     */
1185    public synchronized void setShowVisualIndicator(boolean flag) {
1186        if (mShowVisualIndicator != flag) {
1187            mShowVisualIndicator = flag;
1188            postSync();
1189        }
1190    }
1191
1192    /**
1193     * @return True if the WebView is showing the visual indicator
1194     */
1195    public synchronized boolean getShowVisualIndicator() {
1196        return mShowVisualIndicator;
1197    }
1198
1199    /**
1200     * @see android.webkit.WebSettings#setPluginsEnabled(boolean)
1201     */
1202    @Override
1203    @Deprecated
1204    public synchronized void setPluginsEnabled(boolean flag) {
1205        setPluginState(flag ? PluginState.ON : PluginState.OFF);
1206    }
1207
1208    /**
1209     * @see android.webkit.WebSettings#setPluginState(android.webkit.WebSettingsClassic.PluginState)
1210     */
1211    @Override
1212    public synchronized void setPluginState(PluginState state) {
1213        if (mPluginState != state) {
1214            mPluginState = state;
1215            postSync();
1216        }
1217    }
1218
1219    /**
1220     * @see android.webkit.WebSettings#setPluginsPath(java.lang.String)
1221     */
1222    @Override
1223    @Deprecated
1224    public synchronized void setPluginsPath(String pluginsPath) {
1225    }
1226
1227    /**
1228     * @see android.webkit.WebSettings#setDatabasePath(java.lang.String)
1229     */
1230    @Override
1231    public synchronized void setDatabasePath(String databasePath) {
1232        if (databasePath != null && !mDatabasePathHasBeenSet) {
1233            mDatabasePath = databasePath;
1234            mDatabasePathHasBeenSet = true;
1235            postSync();
1236        }
1237    }
1238
1239    /**
1240     * @see android.webkit.WebSettings#setGeolocationDatabasePath(java.lang.String)
1241     */
1242    @Override
1243    public synchronized void setGeolocationDatabasePath(String databasePath) {
1244        if (databasePath != null
1245                && !databasePath.equals(mGeolocationDatabasePath)) {
1246            mGeolocationDatabasePath = databasePath;
1247            postSync();
1248        }
1249    }
1250
1251    /**
1252     * @see android.webkit.WebSettings#setAppCacheEnabled(boolean)
1253     */
1254    @Override
1255    public synchronized void setAppCacheEnabled(boolean flag) {
1256        if (mAppCacheEnabled != flag) {
1257            mAppCacheEnabled = flag;
1258            postSync();
1259        }
1260    }
1261
1262    /**
1263     * @see android.webkit.WebSettings#setAppCachePath(java.lang.String)
1264     */
1265    @Override
1266    public synchronized void setAppCachePath(String path) {
1267        // We test for a valid path and for repeated setting on the native
1268        // side, but we can avoid syncing in some simple cases.
1269        if (mAppCachePath == null && path != null && !path.isEmpty()) {
1270            mAppCachePath = path;
1271            postSync();
1272        }
1273    }
1274
1275    /**
1276     * @see android.webkit.WebSettings#setAppCacheMaxSize(long)
1277     */
1278    @Override
1279    public synchronized void setAppCacheMaxSize(long appCacheMaxSize) {
1280        if (appCacheMaxSize != mAppCacheMaxSize) {
1281            mAppCacheMaxSize = appCacheMaxSize;
1282            postSync();
1283        }
1284    }
1285
1286    /**
1287     * @see android.webkit.WebSettings#setDatabaseEnabled(boolean)
1288     */
1289    @Override
1290    public synchronized void setDatabaseEnabled(boolean flag) {
1291       if (mDatabaseEnabled != flag) {
1292           mDatabaseEnabled = flag;
1293           postSync();
1294       }
1295    }
1296
1297    /**
1298     * @see android.webkit.WebSettings#setDomStorageEnabled(boolean)
1299     */
1300    @Override
1301    public synchronized void setDomStorageEnabled(boolean flag) {
1302       if (mDomStorageEnabled != flag) {
1303           mDomStorageEnabled = flag;
1304           postSync();
1305       }
1306    }
1307
1308    /**
1309     * @see android.webkit.WebSettings#getDomStorageEnabled()
1310     */
1311    @Override
1312    public synchronized boolean getDomStorageEnabled() {
1313       return mDomStorageEnabled;
1314    }
1315
1316    /**
1317     * @see android.webkit.WebSettings#getDatabasePath()
1318     */
1319    @Override
1320    public synchronized String getDatabasePath() {
1321        return mDatabasePath;
1322    }
1323
1324    /**
1325     * @see android.webkit.WebSettings#getDatabaseEnabled()
1326     */
1327    @Override
1328    public synchronized boolean getDatabaseEnabled() {
1329        return mDatabaseEnabled;
1330    }
1331
1332    /**
1333     * Tell the WebView to enable WebWorkers API.
1334     * @param flag True if the WebView should enable WebWorkers.
1335     * Note that this flag only affects V8. JSC does not have
1336     * an equivalent setting.
1337     */
1338    public synchronized void setWorkersEnabled(boolean flag) {
1339        if (mWorkersEnabled != flag) {
1340            mWorkersEnabled = flag;
1341            postSync();
1342        }
1343    }
1344
1345    /**
1346     * @see android.webkit.WebSettings#setGeolocationEnabled(boolean)
1347     */
1348    @Override
1349    public synchronized void setGeolocationEnabled(boolean flag) {
1350        if (mGeolocationEnabled != flag) {
1351            mGeolocationEnabled = flag;
1352            postSync();
1353        }
1354    }
1355
1356    /**
1357     * Sets whether XSS Auditor is enabled.
1358     * Only used by LayoutTestController.
1359     * @param flag Whether XSS Auditor should be enabled.
1360     */
1361    public synchronized void setXSSAuditorEnabled(boolean flag) {
1362        if (mXSSAuditorEnabled != flag) {
1363            mXSSAuditorEnabled = flag;
1364            postSync();
1365        }
1366    }
1367
1368    /**
1369     * Enables/disables HTML5 link "prefetch" parameter.
1370     */
1371    public synchronized void setLinkPrefetchEnabled(boolean flag) {
1372        if (mLinkPrefetchEnabled != flag) {
1373            mLinkPrefetchEnabled = flag;
1374            postSync();
1375        }
1376    }
1377
1378    /**
1379     * @see android.webkit.WebSettings#getJavaScriptEnabled()
1380     */
1381    @Override
1382    public synchronized boolean getJavaScriptEnabled() {
1383        return mJavaScriptEnabled;
1384    }
1385
1386    /**
1387     * @see android.webkit.WebSettings#getAllowUniversalFileAccessFromFileURLs
1388     */
1389    @Override
1390    public synchronized boolean getAllowUniversalAccessFromFileURLs() {
1391        return mAllowUniversalAccessFromFileURLs;
1392    }
1393
1394    /**
1395     * @see android.webkit.WebSettings#getAllowFileAccessFromFileURLs
1396     */
1397    @Override
1398    public synchronized boolean getAllowFileAccessFromFileURLs() {
1399        return mAllowFileAccessFromFileURLs;
1400    }
1401
1402    /**
1403     * @see android.webkit.WebSettings#getPluginsEnabled()
1404     */
1405    @Override
1406    @Deprecated
1407    public synchronized boolean getPluginsEnabled() {
1408        return mPluginState == PluginState.ON;
1409    }
1410
1411    /**
1412     * @see android.webkit.WebSettings#getPluginState()
1413     */
1414    @Override
1415    public synchronized PluginState getPluginState() {
1416        return mPluginState;
1417    }
1418
1419    /**
1420     * @see android.webkit.WebSettings#getPluginsPath()
1421     */
1422    @Override
1423    @Deprecated
1424    public synchronized String getPluginsPath() {
1425        return "";
1426    }
1427
1428    /**
1429     * @see android.webkit.WebSettings#setJavaScriptCanOpenWindowsAutomatically(boolean)
1430     */
1431    @Override
1432    public synchronized void setJavaScriptCanOpenWindowsAutomatically(
1433            boolean flag) {
1434        if (mJavaScriptCanOpenWindowsAutomatically != flag) {
1435            mJavaScriptCanOpenWindowsAutomatically = flag;
1436            postSync();
1437        }
1438    }
1439
1440    /**
1441     * @see android.webkit.WebSettings#getJavaScriptCanOpenWindowsAutomatically()
1442     */
1443    @Override
1444    public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() {
1445        return mJavaScriptCanOpenWindowsAutomatically;
1446    }
1447
1448    /**
1449     * @see android.webkit.WebSettings#setDefaultTextEncodingName(java.lang.String)
1450     */
1451    @Override
1452    public synchronized void setDefaultTextEncodingName(String encoding) {
1453        if (encoding != null && !encoding.equals(mDefaultTextEncoding)) {
1454            mDefaultTextEncoding = encoding;
1455            postSync();
1456        }
1457    }
1458
1459    /**
1460     * @see android.webkit.WebSettings#getDefaultTextEncodingName()
1461     */
1462    @Override
1463    public synchronized String getDefaultTextEncodingName() {
1464        return mDefaultTextEncoding;
1465    }
1466
1467    /**
1468     * @see android.webkit.WebSettings#setUserAgentString(java.lang.String)
1469     */
1470    @Override
1471    public synchronized void setUserAgentString(String ua) {
1472        if (ua == null || ua.length() == 0) {
1473            synchronized(sLockForLocaleSettings) {
1474                Locale currentLocale = Locale.getDefault();
1475                if (!sLocale.equals(currentLocale)) {
1476                    sLocale = currentLocale;
1477                    mAcceptLanguage = getCurrentAcceptLanguage();
1478                }
1479            }
1480            ua = getCurrentUserAgent();
1481            mUseDefaultUserAgent = true;
1482        } else  {
1483            mUseDefaultUserAgent = false;
1484        }
1485
1486        if (!ua.equals(mUserAgent)) {
1487            mUserAgent = ua;
1488            postSync();
1489        }
1490    }
1491
1492    /**
1493     * @see android.webkit.WebSettings#getUserAgentString()
1494     */
1495    @Override
1496    public synchronized String getUserAgentString() {
1497        if (DESKTOP_USERAGENT.equals(mUserAgent) ||
1498                IPHONE_USERAGENT.equals(mUserAgent) ||
1499                !mUseDefaultUserAgent) {
1500            return mUserAgent;
1501        }
1502
1503        boolean doPostSync = false;
1504        synchronized(sLockForLocaleSettings) {
1505            Locale currentLocale = Locale.getDefault();
1506            if (!sLocale.equals(currentLocale)) {
1507                sLocale = currentLocale;
1508                mUserAgent = getCurrentUserAgent();
1509                mAcceptLanguage = getCurrentAcceptLanguage();
1510                doPostSync = true;
1511            }
1512        }
1513        if (doPostSync) {
1514            postSync();
1515        }
1516        return mUserAgent;
1517    }
1518
1519    /* package api to grab the Accept Language string. */
1520    /*package*/ synchronized String getAcceptLanguage() {
1521        synchronized(sLockForLocaleSettings) {
1522            Locale currentLocale = Locale.getDefault();
1523            if (!sLocale.equals(currentLocale)) {
1524                sLocale = currentLocale;
1525                mAcceptLanguage = getCurrentAcceptLanguage();
1526            }
1527        }
1528        return mAcceptLanguage;
1529    }
1530
1531    /* package */ boolean isNarrowColumnLayout() {
1532        return getLayoutAlgorithm() == LayoutAlgorithm.NARROW_COLUMNS;
1533    }
1534
1535    /**
1536     * @see android.webkit.WebSettings#setNeedInitialFocus(boolean)
1537     */
1538    @Override
1539    public void setNeedInitialFocus(boolean flag) {
1540        if (mNeedInitialFocus != flag) {
1541            mNeedInitialFocus = flag;
1542        }
1543    }
1544
1545    /* Package api to get the choice whether it needs to set initial focus. */
1546    /* package */ boolean getNeedInitialFocus() {
1547        return mNeedInitialFocus;
1548    }
1549
1550    /**
1551     * @see android.webkit.WebSettings#setRenderPriority(android.webkit.WebSettingsClassic.RenderPriority)
1552     */
1553    @Override
1554    public synchronized void setRenderPriority(RenderPriority priority) {
1555        if (mRenderPriority != priority) {
1556            mRenderPriority = priority;
1557            mEventHandler.sendMessage(Message.obtain(null,
1558                    EventHandler.PRIORITY));
1559        }
1560    }
1561
1562    /**
1563     * @see android.webkit.WebSettings#setCacheMode(int)
1564     */
1565    @Override
1566    public void setCacheMode(int mode) {
1567        if (mode != mOverrideCacheMode) {
1568            mOverrideCacheMode = mode;
1569            postSync();
1570        }
1571    }
1572
1573    /**
1574     * @see android.webkit.WebSettings#getCacheMode()
1575     */
1576    @Override
1577    public int getCacheMode() {
1578        return mOverrideCacheMode;
1579    }
1580
1581    /**
1582     * If set, webkit alternately shrinks and expands images viewed outside
1583     * of an HTML page to fit the screen. This conflicts with attempts by
1584     * the UI to zoom in and out of an image, so it is set false by default.
1585     * @param shrink Set true to let webkit shrink the standalone image to fit.
1586     */
1587    public void setShrinksStandaloneImagesToFit(boolean shrink) {
1588        if (mShrinksStandaloneImagesToFit != shrink) {
1589            mShrinksStandaloneImagesToFit = shrink;
1590            postSync();
1591        }
1592     }
1593
1594    /**
1595     * Specify the maximum decoded image size. The default is
1596     * 2 megs for small memory devices and 8 megs for large memory devices.
1597     * @param size The maximum decoded size, or zero to set to the default.
1598     */
1599    public void setMaximumDecodedImageSize(long size) {
1600        if (mMaximumDecodedImageSize != size) {
1601            mMaximumDecodedImageSize = size;
1602            postSync();
1603        }
1604    }
1605
1606    /**
1607     * Returns whether to use fixed viewport.  Use fixed viewport
1608     * whenever wide viewport is on.
1609     */
1610    /* package */ boolean getUseFixedViewport() {
1611        return getUseWideViewPort();
1612    }
1613
1614    /**
1615     * Returns whether private browsing is enabled.
1616     */
1617    /* package */ boolean isPrivateBrowsingEnabled() {
1618        return mPrivateBrowsingEnabled;
1619    }
1620
1621    /**
1622     * Sets whether private browsing is enabled.
1623     * @param flag Whether private browsing should be enabled.
1624     */
1625    /* package */ synchronized void setPrivateBrowsingEnabled(boolean flag) {
1626        if (mPrivateBrowsingEnabled != flag) {
1627            mPrivateBrowsingEnabled = flag;
1628
1629            // AutoFill is dependant on private browsing being enabled so
1630            // reset it to take account of the new value of mPrivateBrowsingEnabled.
1631            setAutoFillEnabled(mAutoFillEnabled);
1632
1633            postSync();
1634        }
1635    }
1636
1637    /**
1638     * Returns whether the viewport metatag can disable zooming
1639     */
1640    public boolean forceUserScalable() {
1641        return mForceUserScalable;
1642    }
1643
1644    /**
1645     * Sets whether viewport metatag can disable zooming.
1646     * @param flag Whether or not to forceably enable user scalable.
1647     */
1648    public synchronized void setForceUserScalable(boolean flag) {
1649        mForceUserScalable = flag;
1650    }
1651
1652    synchronized void setSyntheticLinksEnabled(boolean flag) {
1653        if (mSyntheticLinksEnabled != flag) {
1654            mSyntheticLinksEnabled = flag;
1655            postSync();
1656        }
1657    }
1658
1659    public synchronized void setAutoFillEnabled(boolean enabled) {
1660        // AutoFill is always disabled in private browsing mode.
1661        boolean autoFillEnabled = enabled && !mPrivateBrowsingEnabled;
1662        if (mAutoFillEnabled != autoFillEnabled) {
1663            mAutoFillEnabled = autoFillEnabled;
1664            postSync();
1665        }
1666    }
1667
1668    public synchronized boolean getAutoFillEnabled() {
1669        return mAutoFillEnabled;
1670    }
1671
1672    public synchronized void setAutoFillProfile(AutoFillProfile profile) {
1673        if (mAutoFillProfile != profile) {
1674            mAutoFillProfile = profile;
1675            postSync();
1676        }
1677    }
1678
1679    public synchronized AutoFillProfile getAutoFillProfile() {
1680        return mAutoFillProfile;
1681    }
1682
1683    int getDoubleTapToastCount() {
1684        return mDoubleTapToastCount;
1685    }
1686
1687    void setDoubleTapToastCount(int count) {
1688        if (mDoubleTapToastCount != count) {
1689            mDoubleTapToastCount = count;
1690            // write the settings in the non-UI thread
1691            mEventHandler.sendMessage(Message.obtain(null,
1692                    EventHandler.SET_DOUBLE_TAP_TOAST_COUNT));
1693        }
1694    }
1695
1696    public void setProperty(String key, String value) {
1697        if (mWebView.nativeSetProperty(key, value)) {
1698            mWebView.invalidate();
1699        }
1700    }
1701
1702    public String getProperty(String key) {
1703        return mWebView.nativeGetProperty(key);
1704    }
1705
1706    /**
1707     * Transfer messages from the queue to the new WebCoreThread. Called from
1708     * WebCore thread.
1709     */
1710    /*package*/
1711    synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
1712        mBrowserFrame = frame;
1713        if (DebugFlags.WEB_SETTINGS) {
1714            junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
1715        }
1716
1717        SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE,
1718                Context.MODE_PRIVATE);
1719        if (mDoubleTapToastCount > 0) {
1720            mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
1721                    mDoubleTapToastCount);
1722        }
1723        nativeSync(frame.mNativeFrame);
1724        mSyncPending = false;
1725        mEventHandler.createHandler();
1726    }
1727
1728    /**
1729     * Let the Settings object know that our owner is being destroyed.
1730     */
1731    /*package*/
1732    synchronized void onDestroyed() {
1733    }
1734
1735    private int pin(int size) {
1736        // FIXME: 72 is just an arbitrary max text size value.
1737        if (size < 1) {
1738            return 1;
1739        } else if (size > 72) {
1740            return 72;
1741        }
1742        return size;
1743    }
1744
1745    /* Post a SYNC message to handle syncing the native settings. */
1746    private synchronized void postSync() {
1747        // Only post if a sync is not pending
1748        if (!mSyncPending) {
1749            mSyncPending = mEventHandler.sendMessage(
1750                    Message.obtain(null, EventHandler.SYNC));
1751        }
1752    }
1753
1754    // Synchronize the native and java settings.
1755    private native void nativeSync(int nativeFrame);
1756}
1757