1/*
2 * Copyright 2007, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *  * Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 *  * Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#define LOG_TAG "websettings"
27
28#include <config.h>
29#include <wtf/Platform.h>
30
31#include "ApplicationCacheStorage.h"
32#include "BitmapAllocatorAndroid.h"
33#include "CachedResourceLoader.h"
34#include "ChromiumIncludes.h"
35#include "DatabaseTracker.h"
36#include "Database.h"
37#include "Document.h"
38#include "EditorClientAndroid.h"
39#include "FileSystem.h"
40#include "Frame.h"
41#include "FrameLoader.h"
42#include "FrameView.h"
43#include "GeolocationPermissions.h"
44#include "GeolocationPositionCache.h"
45#include "Page.h"
46#include "PageCache.h"
47#include "RenderTable.h"
48#include "SQLiteFileSystem.h"
49#include "Settings.h"
50#include "WebCoreFrameBridge.h"
51#include "WebCoreJni.h"
52#include "WorkerContextExecutionProxy.h"
53#include "WebRequestContext.h"
54#include "WebViewCore.h"
55
56#include <JNIHelp.h>
57#include <utils/misc.h>
58#include <wtf/text/CString.h>
59
60namespace android {
61
62static const int permissionFlags660 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
63
64struct FieldIds {
65    FieldIds(JNIEnv* env, jclass clazz) {
66        mLayoutAlgorithm = env->GetFieldID(clazz, "mLayoutAlgorithm",
67                "Landroid/webkit/WebSettings$LayoutAlgorithm;");
68        mTextSize = env->GetFieldID(clazz, "mTextSize", "I");
69        mStandardFontFamily = env->GetFieldID(clazz, "mStandardFontFamily",
70                "Ljava/lang/String;");
71        mFixedFontFamily = env->GetFieldID(clazz, "mFixedFontFamily",
72                "Ljava/lang/String;");
73        mSansSerifFontFamily = env->GetFieldID(clazz, "mSansSerifFontFamily",
74                "Ljava/lang/String;");
75        mSerifFontFamily = env->GetFieldID(clazz, "mSerifFontFamily",
76                "Ljava/lang/String;");
77        mCursiveFontFamily = env->GetFieldID(clazz, "mCursiveFontFamily",
78                "Ljava/lang/String;");
79        mFantasyFontFamily = env->GetFieldID(clazz, "mFantasyFontFamily",
80                "Ljava/lang/String;");
81        mDefaultTextEncoding = env->GetFieldID(clazz, "mDefaultTextEncoding",
82                "Ljava/lang/String;");
83        mUserAgent = env->GetFieldID(clazz, "mUserAgent",
84                "Ljava/lang/String;");
85        mAcceptLanguage = env->GetFieldID(clazz, "mAcceptLanguage", "Ljava/lang/String;");
86        mMinimumFontSize = env->GetFieldID(clazz, "mMinimumFontSize", "I");
87        mMinimumLogicalFontSize = env->GetFieldID(clazz, "mMinimumLogicalFontSize", "I");
88        mDefaultFontSize = env->GetFieldID(clazz, "mDefaultFontSize", "I");
89        mDefaultFixedFontSize = env->GetFieldID(clazz, "mDefaultFixedFontSize", "I");
90        mLoadsImagesAutomatically = env->GetFieldID(clazz, "mLoadsImagesAutomatically", "Z");
91#ifdef ANDROID_BLOCK_NETWORK_IMAGE
92        mBlockNetworkImage = env->GetFieldID(clazz, "mBlockNetworkImage", "Z");
93#endif
94        mBlockNetworkLoads = env->GetFieldID(clazz, "mBlockNetworkLoads", "Z");
95        mJavaScriptEnabled = env->GetFieldID(clazz, "mJavaScriptEnabled", "Z");
96        mAllowUniversalAccessFromFileURLs = env->GetFieldID(clazz, "mAllowUniversalAccessFromFileURLs", "Z");
97        mAllowFileAccessFromFileURLs = env->GetFieldID(clazz, "mAllowFileAccessFromFileURLs", "Z");
98        mPluginState = env->GetFieldID(clazz, "mPluginState",
99                "Landroid/webkit/WebSettings$PluginState;");
100#if ENABLE(DATABASE)
101        mDatabaseEnabled = env->GetFieldID(clazz, "mDatabaseEnabled", "Z");
102#endif
103#if ENABLE(DOM_STORAGE)
104        mDomStorageEnabled = env->GetFieldID(clazz, "mDomStorageEnabled", "Z");
105#endif
106#if ENABLE(DATABASE) || ENABLE(DOM_STORAGE)
107        // The databases saved to disk for both the SQL and DOM Storage APIs are stored
108        // in the same base directory.
109        mDatabasePath = env->GetFieldID(clazz, "mDatabasePath", "Ljava/lang/String;");
110        mDatabasePathHasBeenSet = env->GetFieldID(clazz, "mDatabasePathHasBeenSet", "Z");
111#endif
112#if ENABLE(OFFLINE_WEB_APPLICATIONS)
113        mAppCacheEnabled = env->GetFieldID(clazz, "mAppCacheEnabled", "Z");
114        mAppCachePath = env->GetFieldID(clazz, "mAppCachePath", "Ljava/lang/String;");
115        mAppCacheMaxSize = env->GetFieldID(clazz, "mAppCacheMaxSize", "J");
116#endif
117#if ENABLE(WORKERS)
118        mWorkersEnabled = env->GetFieldID(clazz, "mWorkersEnabled", "Z");
119#endif
120        mGeolocationEnabled = env->GetFieldID(clazz, "mGeolocationEnabled", "Z");
121        mGeolocationDatabasePath = env->GetFieldID(clazz, "mGeolocationDatabasePath", "Ljava/lang/String;");
122        mXSSAuditorEnabled = env->GetFieldID(clazz, "mXSSAuditorEnabled", "Z");
123#if ENABLE(LINK_PREFETCH)
124        mLinkPrefetchEnabled = env->GetFieldID(clazz, "mLinkPrefetchEnabled", "Z");
125#endif
126        mJavaScriptCanOpenWindowsAutomatically = env->GetFieldID(clazz,
127                "mJavaScriptCanOpenWindowsAutomatically", "Z");
128        mUseWideViewport = env->GetFieldID(clazz, "mUseWideViewport", "Z");
129        mSupportMultipleWindows = env->GetFieldID(clazz, "mSupportMultipleWindows", "Z");
130        mShrinksStandaloneImagesToFit = env->GetFieldID(clazz, "mShrinksStandaloneImagesToFit", "Z");
131        mMaximumDecodedImageSize = env->GetFieldID(clazz, "mMaximumDecodedImageSize", "J");
132        mPrivateBrowsingEnabled = env->GetFieldID(clazz, "mPrivateBrowsingEnabled", "Z");
133        mSyntheticLinksEnabled = env->GetFieldID(clazz, "mSyntheticLinksEnabled", "Z");
134        mUseDoubleTree = env->GetFieldID(clazz, "mUseDoubleTree", "Z");
135        mPageCacheCapacity = env->GetFieldID(clazz, "mPageCacheCapacity", "I");
136#if ENABLE(WEB_AUTOFILL)
137        mAutoFillEnabled = env->GetFieldID(clazz, "mAutoFillEnabled", "Z");
138        mAutoFillProfile = env->GetFieldID(clazz, "mAutoFillProfile", "Landroid/webkit/WebSettingsClassic$AutoFillProfile;");
139        jclass autoFillProfileClass = env->FindClass("android/webkit/WebSettingsClassic$AutoFillProfile");
140        mAutoFillProfileFullName = env->GetFieldID(autoFillProfileClass, "mFullName", "Ljava/lang/String;");
141        mAutoFillProfileEmailAddress = env->GetFieldID(autoFillProfileClass, "mEmailAddress", "Ljava/lang/String;");
142        mAutoFillProfileCompanyName = env->GetFieldID(autoFillProfileClass, "mCompanyName", "Ljava/lang/String;");
143        mAutoFillProfileAddressLine1 = env->GetFieldID(autoFillProfileClass, "mAddressLine1", "Ljava/lang/String;");
144        mAutoFillProfileAddressLine2 = env->GetFieldID(autoFillProfileClass, "mAddressLine2", "Ljava/lang/String;");
145        mAutoFillProfileCity = env->GetFieldID(autoFillProfileClass, "mCity", "Ljava/lang/String;");
146        mAutoFillProfileState = env->GetFieldID(autoFillProfileClass, "mState", "Ljava/lang/String;");
147        mAutoFillProfileZipCode = env->GetFieldID(autoFillProfileClass, "mZipCode", "Ljava/lang/String;");
148        mAutoFillProfileCountry = env->GetFieldID(autoFillProfileClass, "mCountry", "Ljava/lang/String;");
149        mAutoFillProfilePhoneNumber = env->GetFieldID(autoFillProfileClass, "mPhoneNumber", "Ljava/lang/String;");
150        env->DeleteLocalRef(autoFillProfileClass);
151#endif
152        mOverrideCacheMode = env->GetFieldID(clazz, "mOverrideCacheMode", "I");
153        mPasswordEchoEnabled = env->GetFieldID(clazz, "mPasswordEchoEnabled", "Z");
154
155        ALOG_ASSERT(mLayoutAlgorithm, "Could not find field mLayoutAlgorithm");
156        ALOG_ASSERT(mTextSize, "Could not find field mTextSize");
157        ALOG_ASSERT(mStandardFontFamily, "Could not find field mStandardFontFamily");
158        ALOG_ASSERT(mFixedFontFamily, "Could not find field mFixedFontFamily");
159        ALOG_ASSERT(mSansSerifFontFamily, "Could not find field mSansSerifFontFamily");
160        ALOG_ASSERT(mSerifFontFamily, "Could not find field mSerifFontFamily");
161        ALOG_ASSERT(mCursiveFontFamily, "Could not find field mCursiveFontFamily");
162        ALOG_ASSERT(mFantasyFontFamily, "Could not find field mFantasyFontFamily");
163        ALOG_ASSERT(mDefaultTextEncoding, "Could not find field mDefaultTextEncoding");
164        ALOG_ASSERT(mUserAgent, "Could not find field mUserAgent");
165        ALOG_ASSERT(mAcceptLanguage, "Could not find field mAcceptLanguage");
166        ALOG_ASSERT(mMinimumFontSize, "Could not find field mMinimumFontSize");
167        ALOG_ASSERT(mMinimumLogicalFontSize, "Could not find field mMinimumLogicalFontSize");
168        ALOG_ASSERT(mDefaultFontSize, "Could not find field mDefaultFontSize");
169        ALOG_ASSERT(mDefaultFixedFontSize, "Could not find field mDefaultFixedFontSize");
170        ALOG_ASSERT(mLoadsImagesAutomatically, "Could not find field mLoadsImagesAutomatically");
171#ifdef ANDROID_BLOCK_NETWORK_IMAGE
172        ALOG_ASSERT(mBlockNetworkImage, "Could not find field mBlockNetworkImage");
173#endif
174        ALOG_ASSERT(mBlockNetworkLoads, "Could not find field mBlockNetworkLoads");
175        ALOG_ASSERT(mJavaScriptEnabled, "Could not find field mJavaScriptEnabled");
176        ALOG_ASSERT(mAllowUniversalAccessFromFileURLs,
177                    "Could not find field mAllowUniversalAccessFromFileURLs");
178        ALOG_ASSERT(mAllowFileAccessFromFileURLs,
179                    "Could not find field mAllowFileAccessFromFileURLs");
180        ALOG_ASSERT(mPluginState, "Could not find field mPluginState");
181#if ENABLE(OFFLINE_WEB_APPLICATIONS)
182        ALOG_ASSERT(mAppCacheEnabled, "Could not find field mAppCacheEnabled");
183        ALOG_ASSERT(mAppCachePath, "Could not find field mAppCachePath");
184        ALOG_ASSERT(mAppCacheMaxSize, "Could not find field mAppCacheMaxSize");
185#endif
186#if ENABLE(WORKERS)
187        ALOG_ASSERT(mWorkersEnabled, "Could not find field mWorkersEnabled");
188#endif
189        ALOG_ASSERT(mJavaScriptCanOpenWindowsAutomatically,
190                "Could not find field mJavaScriptCanOpenWindowsAutomatically");
191        ALOG_ASSERT(mUseWideViewport, "Could not find field mUseWideViewport");
192        ALOG_ASSERT(mSupportMultipleWindows, "Could not find field mSupportMultipleWindows");
193        ALOG_ASSERT(mShrinksStandaloneImagesToFit, "Could not find field mShrinksStandaloneImagesToFit");
194        ALOG_ASSERT(mMaximumDecodedImageSize, "Could not find field mMaximumDecodedImageSize");
195        ALOG_ASSERT(mUseDoubleTree, "Could not find field mUseDoubleTree");
196        ALOG_ASSERT(mPageCacheCapacity, "Could not find field mPageCacheCapacity");
197        ALOG_ASSERT(mPasswordEchoEnabled, "Could not find field mPasswordEchoEnabled");
198
199        jclass enumClass = env->FindClass("java/lang/Enum");
200        ALOG_ASSERT(enumClass, "Could not find Enum class!");
201        mOrdinal = env->GetMethodID(enumClass, "ordinal", "()I");
202        ALOG_ASSERT(mOrdinal, "Could not find method ordinal");
203        env->DeleteLocalRef(enumClass);
204    }
205
206    // Field ids
207    jfieldID mLayoutAlgorithm;
208    jfieldID mTextSize;
209    jfieldID mStandardFontFamily;
210    jfieldID mFixedFontFamily;
211    jfieldID mSansSerifFontFamily;
212    jfieldID mSerifFontFamily;
213    jfieldID mCursiveFontFamily;
214    jfieldID mFantasyFontFamily;
215    jfieldID mDefaultTextEncoding;
216    jfieldID mUserAgent;
217    jfieldID mAcceptLanguage;
218    jfieldID mMinimumFontSize;
219    jfieldID mMinimumLogicalFontSize;
220    jfieldID mDefaultFontSize;
221    jfieldID mDefaultFixedFontSize;
222    jfieldID mLoadsImagesAutomatically;
223#ifdef ANDROID_BLOCK_NETWORK_IMAGE
224    jfieldID mBlockNetworkImage;
225#endif
226    jfieldID mBlockNetworkLoads;
227    jfieldID mJavaScriptEnabled;
228    jfieldID mAllowUniversalAccessFromFileURLs;
229    jfieldID mAllowFileAccessFromFileURLs;
230    jfieldID mPluginState;
231#if ENABLE(OFFLINE_WEB_APPLICATIONS)
232    jfieldID mAppCacheEnabled;
233    jfieldID mAppCachePath;
234    jfieldID mAppCacheMaxSize;
235#endif
236#if ENABLE(WORKERS)
237    jfieldID mWorkersEnabled;
238#endif
239    jfieldID mJavaScriptCanOpenWindowsAutomatically;
240    jfieldID mUseWideViewport;
241    jfieldID mSupportMultipleWindows;
242    jfieldID mShrinksStandaloneImagesToFit;
243    jfieldID mMaximumDecodedImageSize;
244    jfieldID mPrivateBrowsingEnabled;
245    jfieldID mSyntheticLinksEnabled;
246    jfieldID mUseDoubleTree;
247    jfieldID mPageCacheCapacity;
248    // Ordinal() method and value field for enums
249    jmethodID mOrdinal;
250    jfieldID  mTextSizeValue;
251
252#if ENABLE(DATABASE)
253    jfieldID mDatabaseEnabled;
254#endif
255#if ENABLE(DOM_STORAGE)
256    jfieldID mDomStorageEnabled;
257#endif
258    jfieldID mGeolocationEnabled;
259    jfieldID mGeolocationDatabasePath;
260    jfieldID mXSSAuditorEnabled;
261#if ENABLE(LINK_PREFETCH)
262    jfieldID mLinkPrefetchEnabled;
263#endif
264#if ENABLE(DATABASE) || ENABLE(DOM_STORAGE)
265    jfieldID mDatabasePath;
266    jfieldID mDatabasePathHasBeenSet;
267#endif
268#if ENABLE(WEB_AUTOFILL)
269    jfieldID mAutoFillEnabled;
270    jfieldID mAutoFillProfile;
271    jfieldID mAutoFillProfileFullName;
272    jfieldID mAutoFillProfileEmailAddress;
273    jfieldID mAutoFillProfileCompanyName;
274    jfieldID mAutoFillProfileAddressLine1;
275    jfieldID mAutoFillProfileAddressLine2;
276    jfieldID mAutoFillProfileCity;
277    jfieldID mAutoFillProfileState;
278    jfieldID mAutoFillProfileZipCode;
279    jfieldID mAutoFillProfileCountry;
280    jfieldID mAutoFillProfilePhoneNumber;
281#endif
282    jfieldID mOverrideCacheMode;
283    jfieldID mPasswordEchoEnabled;
284};
285
286static struct FieldIds* gFieldIds;
287
288// Note: This is moved from the old FrameAndroid.cpp
289static void recursiveCleanupForFullLayout(WebCore::RenderObject* obj)
290{
291    obj->setNeedsLayout(true, false);
292#ifdef ANDROID_LAYOUT
293    if (obj->isTable())
294        (static_cast<WebCore::RenderTable *>(obj))->clearSingleColumn();
295#endif
296    for (WebCore::RenderObject* n = obj->firstChild(); n; n = n->nextSibling())
297        recursiveCleanupForFullLayout(n);
298}
299
300#if ENABLE(WEB_AUTOFILL)
301inline string16 getStringFieldAsString16(JNIEnv* env, jobject autoFillProfile, jfieldID fieldId)
302{
303    jstring str = static_cast<jstring>(env->GetObjectField(autoFillProfile, fieldId));
304    return str ? jstringToString16(env, str) : string16();
305}
306
307void syncAutoFillProfile(JNIEnv* env, jobject autoFillProfile, WebAutofill* webAutofill)
308{
309    string16 fullName = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileFullName);
310    string16 emailAddress = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileEmailAddress);
311    string16 companyName = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileCompanyName);
312    string16 addressLine1 = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileAddressLine1);
313    string16 addressLine2 = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileAddressLine2);
314    string16 city = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileCity);
315    string16 state = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileState);
316    string16 zipCode = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileZipCode);
317    string16 country = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileCountry);
318    string16 phoneNumber = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfilePhoneNumber);
319
320    webAutofill->setProfile(fullName, emailAddress, companyName, addressLine1, addressLine2, city, state, zipCode, country, phoneNumber);
321}
322#endif
323
324class WebSettings {
325public:
326    static void Sync(JNIEnv* env, jobject obj, jint frame)
327    {
328        WebCore::Frame* pFrame = (WebCore::Frame*)frame;
329        ALOG_ASSERT(pFrame, "%s must take a valid frame pointer!", __FUNCTION__);
330        WebCore::Settings* s = pFrame->settings();
331        if (!s)
332            return;
333        WebCore::CachedResourceLoader* cachedResourceLoader = pFrame->document()->cachedResourceLoader();
334
335#ifdef ANDROID_LAYOUT
336        jobject layout = env->GetObjectField(obj, gFieldIds->mLayoutAlgorithm);
337        WebCore::Settings::LayoutAlgorithm l = (WebCore::Settings::LayoutAlgorithm)
338                env->CallIntMethod(layout, gFieldIds->mOrdinal);
339        if (s->layoutAlgorithm() != l) {
340            s->setLayoutAlgorithm(l);
341            if (pFrame->document()) {
342                pFrame->document()->styleSelectorChanged(WebCore::RecalcStyleImmediately);
343                if (pFrame->document()->renderer()) {
344                    recursiveCleanupForFullLayout(pFrame->document()->renderer());
345                    ALOG_ASSERT(pFrame->view(), "No view for this frame when trying to relayout");
346                    pFrame->view()->layout();
347                    // FIXME: This call used to scroll the page to put the focus into view.
348                    // It worked on the WebViewCore, but now scrolling is done outside of the
349                    // WebViewCore, on the UI side, so there needs to be a new way to do this.
350                    //pFrame->makeFocusVisible();
351                }
352            }
353        }
354#endif
355        jint textSize = env->GetIntField(obj, gFieldIds->mTextSize);
356        float zoomFactor = textSize / 100.0f;
357        if (pFrame->textZoomFactor() != zoomFactor)
358            pFrame->setTextZoomFactor(zoomFactor);
359
360        jstring str = (jstring)env->GetObjectField(obj, gFieldIds->mStandardFontFamily);
361        s->setStandardFontFamily(jstringToWtfString(env, str));
362
363        str = (jstring)env->GetObjectField(obj, gFieldIds->mFixedFontFamily);
364        s->setFixedFontFamily(jstringToWtfString(env, str));
365
366        str = (jstring)env->GetObjectField(obj, gFieldIds->mSansSerifFontFamily);
367        s->setSansSerifFontFamily(jstringToWtfString(env, str));
368
369        str = (jstring)env->GetObjectField(obj, gFieldIds->mSerifFontFamily);
370        s->setSerifFontFamily(jstringToWtfString(env, str));
371
372        str = (jstring)env->GetObjectField(obj, gFieldIds->mCursiveFontFamily);
373        s->setCursiveFontFamily(jstringToWtfString(env, str));
374
375        str = (jstring)env->GetObjectField(obj, gFieldIds->mFantasyFontFamily);
376        s->setFantasyFontFamily(jstringToWtfString(env, str));
377
378        str = (jstring)env->GetObjectField(obj, gFieldIds->mDefaultTextEncoding);
379        s->setDefaultTextEncodingName(jstringToWtfString(env, str));
380
381        str = (jstring)env->GetObjectField(obj, gFieldIds->mUserAgent);
382        WebFrame::getWebFrame(pFrame)->setUserAgent(jstringToWtfString(env, str));
383        WebViewCore::getWebViewCore(pFrame->view())->setWebRequestContextUserAgent();
384
385        jint cacheMode = env->GetIntField(obj, gFieldIds->mOverrideCacheMode);
386        WebViewCore::getWebViewCore(pFrame->view())->setWebRequestContextCacheMode(cacheMode);
387
388        str = (jstring)env->GetObjectField(obj, gFieldIds->mAcceptLanguage);
389        WebRequestContext::setAcceptLanguage(jstringToWtfString(env, str));
390
391        jint size = env->GetIntField(obj, gFieldIds->mMinimumFontSize);
392        s->setMinimumFontSize(size);
393
394        size = env->GetIntField(obj, gFieldIds->mMinimumLogicalFontSize);
395        s->setMinimumLogicalFontSize(size);
396
397        size = env->GetIntField(obj, gFieldIds->mDefaultFontSize);
398        s->setDefaultFontSize(size);
399
400        size = env->GetIntField(obj, gFieldIds->mDefaultFixedFontSize);
401        s->setDefaultFixedFontSize(size);
402
403        jboolean flag = env->GetBooleanField(obj, gFieldIds->mLoadsImagesAutomatically);
404        s->setLoadsImagesAutomatically(flag);
405        if (flag)
406            cachedResourceLoader->setAutoLoadImages(true);
407
408#ifdef ANDROID_BLOCK_NETWORK_IMAGE
409        flag = env->GetBooleanField(obj, gFieldIds->mBlockNetworkImage);
410        s->setBlockNetworkImage(flag);
411        if(!flag)
412            cachedResourceLoader->setBlockNetworkImage(false);
413#endif
414        flag = env->GetBooleanField(obj, gFieldIds->mBlockNetworkLoads);
415        WebFrame* webFrame = WebFrame::getWebFrame(pFrame);
416        webFrame->setBlockNetworkLoads(flag);
417
418        flag = env->GetBooleanField(obj, gFieldIds->mJavaScriptEnabled);
419        s->setJavaScriptEnabled(flag);
420
421        flag = env->GetBooleanField(obj, gFieldIds->mAllowUniversalAccessFromFileURLs);
422        s->setAllowUniversalAccessFromFileURLs(flag);
423
424        flag = env->GetBooleanField(obj, gFieldIds->mAllowFileAccessFromFileURLs);
425        s->setAllowFileAccessFromFileURLs(flag);
426
427        // Hyperlink auditing (the ping attribute) has similar privacy
428        // considerations as does the running of JavaScript, so to keep the UI
429        // simpler, we leverage the same setting.
430        s->setHyperlinkAuditingEnabled(flag);
431
432        // ON = 0
433        // ON_DEMAND = 1
434        // OFF = 2
435        jobject pluginState = env->GetObjectField(obj, gFieldIds->mPluginState);
436        int state = env->CallIntMethod(pluginState, gFieldIds->mOrdinal);
437        s->setPluginsEnabled(state < 2);
438#ifdef ANDROID_PLUGINS
439        s->setPluginsOnDemand(state == 1);
440#endif
441
442#if ENABLE(OFFLINE_WEB_APPLICATIONS)
443        // We only enable AppCache if it's been enabled with a call to
444        // setAppCacheEnabled() and if a valid path has been supplied to
445        // setAppCachePath(). Note that the path is applied to all WebViews
446        // whereas enabling is applied per WebView.
447
448        // WebCore asserts that the path is only set once. Since the path is
449        // shared between WebViews, we can't do the required checks to guard
450        // against this in the Java WebSettings.
451        bool isPathValid = false;
452        if (cacheStorage().cacheDirectory().isNull()) {
453            str = static_cast<jstring>(env->GetObjectField(obj, gFieldIds->mAppCachePath));
454            // Check for non-null string as an optimization, as this is the common case.
455            if (str) {
456                String path = jstringToWtfString(env, str);
457                ALOG_ASSERT(!path.empty(), "Java side should never send empty string for AppCache path");
458                // This database is created on the first load. If the file
459                // doesn't exist, we create it and set its permissions. The
460                // filename must match that in ApplicationCacheStorage.cpp.
461                String filename = pathByAppendingComponent(path, "ApplicationCache.db");
462                int fd = open(filename.utf8().data(), O_CREAT, permissionFlags660);
463                if (fd >= 0) {
464                    close(fd);
465                    cacheStorage().setCacheDirectory(path);
466                    isPathValid = true;
467              }
468            }
469        } else
470            isPathValid = true;
471
472        flag = env->GetBooleanField(obj, gFieldIds->mAppCacheEnabled);
473        s->setOfflineWebApplicationCacheEnabled(flag && isPathValid);
474
475        jlong maxsize = env->GetLongField(obj, gFieldIds->mAppCacheMaxSize);
476        cacheStorage().setMaximumSize(maxsize);
477#endif
478
479        flag = env->GetBooleanField(obj, gFieldIds->mJavaScriptCanOpenWindowsAutomatically);
480        s->setJavaScriptCanOpenWindowsAutomatically(flag);
481
482#ifdef ANDROID_LAYOUT
483        flag = env->GetBooleanField(obj, gFieldIds->mUseWideViewport);
484        s->setUseWideViewport(flag);
485#endif
486
487#ifdef ANDROID_MULTIPLE_WINDOWS
488        flag = env->GetBooleanField(obj, gFieldIds->mSupportMultipleWindows);
489        s->setSupportMultipleWindows(flag);
490#endif
491        flag = env->GetBooleanField(obj, gFieldIds->mShrinksStandaloneImagesToFit);
492        s->setShrinksStandaloneImagesToFit(flag);
493        jlong maxImage = env->GetLongField(obj, gFieldIds->mMaximumDecodedImageSize);
494        // Since in ImageSourceAndroid.cpp, the image will always not exceed
495        // MAX_SIZE_BEFORE_SUBSAMPLE, there's no need to pass the max value to
496        // WebCore, which checks (image_width * image_height * 4) as an
497        // estimation against the max value, which is done in CachedImage.cpp.
498        // And there're cases where the decoded image size will not
499        // exceed the max, but the WebCore estimation will.  So the following
500        // code is commented out to fix those cases.
501        // if (maxImage == 0)
502        //    maxImage = computeMaxBitmapSizeForCache();
503        s->setMaximumDecodedImageSize(maxImage);
504
505        flag = env->GetBooleanField(obj, gFieldIds->mPrivateBrowsingEnabled);
506        s->setPrivateBrowsingEnabled(flag);
507
508        flag = env->GetBooleanField(obj, gFieldIds->mSyntheticLinksEnabled);
509        s->setDefaultFormatDetection(flag);
510        s->setFormatDetectionAddress(flag);
511        s->setFormatDetectionEmail(flag);
512        s->setFormatDetectionTelephone(flag);
513#if ENABLE(DATABASE)
514        flag = env->GetBooleanField(obj, gFieldIds->mDatabaseEnabled);
515        WebCore::Database::setIsAvailable(flag);
516
517        flag = env->GetBooleanField(obj, gFieldIds->mDatabasePathHasBeenSet);
518        if (flag) {
519            // If the user has set the database path, sync it to the DatabaseTracker.
520            str = (jstring)env->GetObjectField(obj, gFieldIds->mDatabasePath);
521            if (str) {
522                String path = jstringToWtfString(env, str);
523                DatabaseTracker::tracker().setDatabaseDirectoryPath(path);
524                // This database is created when the first HTML5 Database object is
525                // instantiated. If the file doesn't exist, we create it and set its
526                // permissions. The filename must match that in
527                // DatabaseTracker.cpp.
528                String filename = SQLiteFileSystem::appendDatabaseFileNameToPath(path, "Databases.db");
529                int fd = open(filename.utf8().data(), O_CREAT | O_EXCL, permissionFlags660);
530                if (fd >= 0)
531                    close(fd);
532            }
533        }
534#endif
535#if ENABLE(DOM_STORAGE)
536        flag = env->GetBooleanField(obj, gFieldIds->mDomStorageEnabled);
537        s->setLocalStorageEnabled(flag);
538        str = (jstring)env->GetObjectField(obj, gFieldIds->mDatabasePath);
539        if (str) {
540            WTF::String localStorageDatabasePath = jstringToWtfString(env,str);
541            if (localStorageDatabasePath.length()) {
542                localStorageDatabasePath = WebCore::pathByAppendingComponent(
543                        localStorageDatabasePath, "localstorage");
544                // We need 770 for folders
545                mkdir(localStorageDatabasePath.utf8().data(),
546                        permissionFlags660 | S_IXUSR | S_IXGRP);
547                s->setLocalStorageDatabasePath(localStorageDatabasePath);
548            }
549        }
550#endif
551
552        flag = env->GetBooleanField(obj, gFieldIds->mGeolocationEnabled);
553        GeolocationPermissions::setAlwaysDeny(!flag);
554        str = (jstring)env->GetObjectField(obj, gFieldIds->mGeolocationDatabasePath);
555        if (str) {
556            String path = jstringToWtfString(env, str);
557            GeolocationPermissions::setDatabasePath(path);
558            GeolocationPositionCache::instance()->setDatabasePath(path);
559            // This database is created when the first Geolocation object is
560            // instantiated. If the file doesn't exist, we create it and set its
561            // permissions. The filename must match that in
562            // GeolocationPositionCache.cpp.
563            String filename = SQLiteFileSystem::appendDatabaseFileNameToPath(path, "CachedGeoposition.db");
564            int fd = open(filename.utf8().data(), O_CREAT | O_EXCL, permissionFlags660);
565            if (fd >= 0)
566                close(fd);
567        }
568
569        flag = env->GetBooleanField(obj, gFieldIds->mXSSAuditorEnabled);
570        s->setXSSAuditorEnabled(flag);
571
572#if ENABLE(LINK_PREFETCH)
573        flag = env->GetBooleanField(obj, gFieldIds->mLinkPrefetchEnabled);
574        s->setLinkPrefetchEnabled(flag);
575#endif
576
577        size = env->GetIntField(obj, gFieldIds->mPageCacheCapacity);
578        if (size > 0) {
579            s->setUsesPageCache(true);
580            WebCore::pageCache()->setCapacity(size);
581        } else
582            s->setUsesPageCache(false);
583
584#if ENABLE(WEB_AUTOFILL)
585        flag = env->GetBooleanField(obj, gFieldIds->mAutoFillEnabled);
586        // TODO: This updates the Settings WebCore side with the user's
587        // preference for autofill and will stop WebCore making requests
588        // into the chromium autofill code. That code in Chromium also has
589        // a notion of being enabled/disabled that gets read from the users
590        // preferences. At the moment, it's hardcoded to true on Android
591        // (see chrome/browser/autofill/autofill_manager.cc:405). This
592        // setting should probably be synced into Chromium also.
593
594        s->setAutoFillEnabled(flag);
595
596        if (flag) {
597            EditorClientAndroid* editorC = static_cast<EditorClientAndroid*>(pFrame->page()->editorClient());
598            WebAutofill* webAutofill = editorC->getAutofill();
599            // Set the active AutofillProfile data.
600            jobject autoFillProfile = env->GetObjectField(obj, gFieldIds->mAutoFillProfile);
601            if (autoFillProfile)
602                syncAutoFillProfile(env, autoFillProfile, webAutofill);
603            else {
604                // The autofill profile is null. We need to tell Chromium about this because
605                // this may be because the user just deleted their profile but left the
606                // autofill feature setting enabled.
607                webAutofill->clearProfiles();
608            }
609        }
610#endif
611
612        // This is required to enable the XMLTreeViewer when loading an XML document that
613        // has no style attached to it. http://trac.webkit.org/changeset/79799
614        s->setDeveloperExtrasEnabled(true);
615        s->setSpatialNavigationEnabled(true);
616        bool echoPassword = env->GetBooleanField(obj,
617                gFieldIds->mPasswordEchoEnabled);
618        s->setPasswordEchoEnabled(echoPassword);
619    }
620};
621
622
623//-------------------------------------------------------------
624// JNI registration
625//-------------------------------------------------------------
626
627static JNINativeMethod gWebSettingsMethods[] = {
628    { "nativeSync", "(I)V",
629        (void*) WebSettings::Sync }
630};
631
632int registerWebSettings(JNIEnv* env)
633{
634    jclass clazz = env->FindClass("android/webkit/WebSettingsClassic");
635    ALOG_ASSERT(clazz, "Unable to find class WebSettingsClassic!");
636    gFieldIds = new FieldIds(env, clazz);
637    env->DeleteLocalRef(clazz);
638    return jniRegisterNativeMethods(env, "android/webkit/WebSettingsClassic",
639            gWebSettingsMethods, NELEM(gWebSettingsMethods));
640}
641
642}
643