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