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#if USE(V8)
53#include "WorkerContextExecutionProxy.h"
54#endif
55#include "WebRequestContext.h"
56#include "WebViewCore.h"
57
58#include <JNIHelp.h>
59#include <utils/misc.h>
60#include <wtf/text/CString.h>
61
62namespace android {
63
64static const int permissionFlags660 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
65
66struct FieldIds {
67    FieldIds(JNIEnv* env, jclass clazz) {
68        mLayoutAlgorithm = env->GetFieldID(clazz, "mLayoutAlgorithm",
69                "Landroid/webkit/WebSettings$LayoutAlgorithm;");
70        mTextSize = env->GetFieldID(clazz, "mTextSize", "I");
71        mStandardFontFamily = env->GetFieldID(clazz, "mStandardFontFamily",
72                "Ljava/lang/String;");
73        mFixedFontFamily = env->GetFieldID(clazz, "mFixedFontFamily",
74                "Ljava/lang/String;");
75        mSansSerifFontFamily = env->GetFieldID(clazz, "mSansSerifFontFamily",
76                "Ljava/lang/String;");
77        mSerifFontFamily = env->GetFieldID(clazz, "mSerifFontFamily",
78                "Ljava/lang/String;");
79        mCursiveFontFamily = env->GetFieldID(clazz, "mCursiveFontFamily",
80                "Ljava/lang/String;");
81        mFantasyFontFamily = env->GetFieldID(clazz, "mFantasyFontFamily",
82                "Ljava/lang/String;");
83        mDefaultTextEncoding = env->GetFieldID(clazz, "mDefaultTextEncoding",
84                "Ljava/lang/String;");
85        mUserAgent = env->GetFieldID(clazz, "mUserAgent",
86                "Ljava/lang/String;");
87        mAcceptLanguage = env->GetFieldID(clazz, "mAcceptLanguage", "Ljava/lang/String;");
88        mMinimumFontSize = env->GetFieldID(clazz, "mMinimumFontSize", "I");
89        mMinimumLogicalFontSize = env->GetFieldID(clazz, "mMinimumLogicalFontSize", "I");
90        mDefaultFontSize = env->GetFieldID(clazz, "mDefaultFontSize", "I");
91        mDefaultFixedFontSize = env->GetFieldID(clazz, "mDefaultFixedFontSize", "I");
92        mLoadsImagesAutomatically = env->GetFieldID(clazz, "mLoadsImagesAutomatically", "Z");
93#ifdef ANDROID_BLOCK_NETWORK_IMAGE
94        mBlockNetworkImage = env->GetFieldID(clazz, "mBlockNetworkImage", "Z");
95#endif
96        mBlockNetworkLoads = env->GetFieldID(clazz, "mBlockNetworkLoads", "Z");
97        mJavaScriptEnabled = env->GetFieldID(clazz, "mJavaScriptEnabled", "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        mJavaScriptCanOpenWindowsAutomatically = env->GetFieldID(clazz,
124                "mJavaScriptCanOpenWindowsAutomatically", "Z");
125        mUseWideViewport = env->GetFieldID(clazz, "mUseWideViewport", "Z");
126        mSupportMultipleWindows = env->GetFieldID(clazz, "mSupportMultipleWindows", "Z");
127        mShrinksStandaloneImagesToFit = env->GetFieldID(clazz, "mShrinksStandaloneImagesToFit", "Z");
128        mMaximumDecodedImageSize = env->GetFieldID(clazz, "mMaximumDecodedImageSize", "J");
129        mPrivateBrowsingEnabled = env->GetFieldID(clazz, "mPrivateBrowsingEnabled", "Z");
130        mSyntheticLinksEnabled = env->GetFieldID(clazz, "mSyntheticLinksEnabled", "Z");
131        mUseDoubleTree = env->GetFieldID(clazz, "mUseDoubleTree", "Z");
132        mPageCacheCapacity = env->GetFieldID(clazz, "mPageCacheCapacity", "I");
133#if ENABLE(WEB_AUTOFILL)
134        mAutoFillEnabled = env->GetFieldID(clazz, "mAutoFillEnabled", "Z");
135        mAutoFillProfile = env->GetFieldID(clazz, "mAutoFillProfile", "Landroid/webkit/WebSettings$AutoFillProfile;");
136        jclass autoFillProfileClass = env->FindClass("android/webkit/WebSettings$AutoFillProfile");
137        mAutoFillProfileFullName = env->GetFieldID(autoFillProfileClass, "mFullName", "Ljava/lang/String;");
138        mAutoFillProfileEmailAddress = env->GetFieldID(autoFillProfileClass, "mEmailAddress", "Ljava/lang/String;");
139        mAutoFillProfileCompanyName = env->GetFieldID(autoFillProfileClass, "mCompanyName", "Ljava/lang/String;");
140        mAutoFillProfileAddressLine1 = env->GetFieldID(autoFillProfileClass, "mAddressLine1", "Ljava/lang/String;");
141        mAutoFillProfileAddressLine2 = env->GetFieldID(autoFillProfileClass, "mAddressLine2", "Ljava/lang/String;");
142        mAutoFillProfileCity = env->GetFieldID(autoFillProfileClass, "mCity", "Ljava/lang/String;");
143        mAutoFillProfileState = env->GetFieldID(autoFillProfileClass, "mState", "Ljava/lang/String;");
144        mAutoFillProfileZipCode = env->GetFieldID(autoFillProfileClass, "mZipCode", "Ljava/lang/String;");
145        mAutoFillProfileCountry = env->GetFieldID(autoFillProfileClass, "mCountry", "Ljava/lang/String;");
146        mAutoFillProfilePhoneNumber = env->GetFieldID(autoFillProfileClass, "mPhoneNumber", "Ljava/lang/String;");
147        env->DeleteLocalRef(autoFillProfileClass);
148#endif
149#if USE(CHROME_NETWORK_STACK)
150        mOverrideCacheMode = env->GetFieldID(clazz, "mOverrideCacheMode", "I");
151#endif
152
153        LOG_ASSERT(mLayoutAlgorithm, "Could not find field mLayoutAlgorithm");
154        LOG_ASSERT(mTextSize, "Could not find field mTextSize");
155        LOG_ASSERT(mStandardFontFamily, "Could not find field mStandardFontFamily");
156        LOG_ASSERT(mFixedFontFamily, "Could not find field mFixedFontFamily");
157        LOG_ASSERT(mSansSerifFontFamily, "Could not find field mSansSerifFontFamily");
158        LOG_ASSERT(mSerifFontFamily, "Could not find field mSerifFontFamily");
159        LOG_ASSERT(mCursiveFontFamily, "Could not find field mCursiveFontFamily");
160        LOG_ASSERT(mFantasyFontFamily, "Could not find field mFantasyFontFamily");
161        LOG_ASSERT(mDefaultTextEncoding, "Could not find field mDefaultTextEncoding");
162        LOG_ASSERT(mUserAgent, "Could not find field mUserAgent");
163        LOG_ASSERT(mAcceptLanguage, "Could not find field mAcceptLanguage");
164        LOG_ASSERT(mMinimumFontSize, "Could not find field mMinimumFontSize");
165        LOG_ASSERT(mMinimumLogicalFontSize, "Could not find field mMinimumLogicalFontSize");
166        LOG_ASSERT(mDefaultFontSize, "Could not find field mDefaultFontSize");
167        LOG_ASSERT(mDefaultFixedFontSize, "Could not find field mDefaultFixedFontSize");
168        LOG_ASSERT(mLoadsImagesAutomatically, "Could not find field mLoadsImagesAutomatically");
169#ifdef ANDROID_BLOCK_NETWORK_IMAGE
170        LOG_ASSERT(mBlockNetworkImage, "Could not find field mBlockNetworkImage");
171#endif
172        LOG_ASSERT(mBlockNetworkLoads, "Could not find field mBlockNetworkLoads");
173        LOG_ASSERT(mJavaScriptEnabled, "Could not find field mJavaScriptEnabled");
174        LOG_ASSERT(mPluginState, "Could not find field mPluginState");
175#if ENABLE(OFFLINE_WEB_APPLICATIONS)
176        LOG_ASSERT(mAppCacheEnabled, "Could not find field mAppCacheEnabled");
177        LOG_ASSERT(mAppCachePath, "Could not find field mAppCachePath");
178        LOG_ASSERT(mAppCacheMaxSize, "Could not find field mAppCacheMaxSize");
179#endif
180#if ENABLE(WORKERS)
181        LOG_ASSERT(mWorkersEnabled, "Could not find field mWorkersEnabled");
182#endif
183        LOG_ASSERT(mJavaScriptCanOpenWindowsAutomatically,
184                "Could not find field mJavaScriptCanOpenWindowsAutomatically");
185        LOG_ASSERT(mUseWideViewport, "Could not find field mUseWideViewport");
186        LOG_ASSERT(mSupportMultipleWindows, "Could not find field mSupportMultipleWindows");
187        LOG_ASSERT(mShrinksStandaloneImagesToFit, "Could not find field mShrinksStandaloneImagesToFit");
188        LOG_ASSERT(mMaximumDecodedImageSize, "Could not find field mMaximumDecodedImageSize");
189        LOG_ASSERT(mUseDoubleTree, "Could not find field mUseDoubleTree");
190        LOG_ASSERT(mPageCacheCapacity, "Could not find field mPageCacheCapacity");
191
192        jclass enumClass = env->FindClass("java/lang/Enum");
193        LOG_ASSERT(enumClass, "Could not find Enum class!");
194        mOrdinal = env->GetMethodID(enumClass, "ordinal", "()I");
195        LOG_ASSERT(mOrdinal, "Could not find method ordinal");
196        env->DeleteLocalRef(enumClass);
197    }
198
199    // Field ids
200    jfieldID mLayoutAlgorithm;
201    jfieldID mTextSize;
202    jfieldID mStandardFontFamily;
203    jfieldID mFixedFontFamily;
204    jfieldID mSansSerifFontFamily;
205    jfieldID mSerifFontFamily;
206    jfieldID mCursiveFontFamily;
207    jfieldID mFantasyFontFamily;
208    jfieldID mDefaultTextEncoding;
209    jfieldID mUserAgent;
210    jfieldID mAcceptLanguage;
211    jfieldID mMinimumFontSize;
212    jfieldID mMinimumLogicalFontSize;
213    jfieldID mDefaultFontSize;
214    jfieldID mDefaultFixedFontSize;
215    jfieldID mLoadsImagesAutomatically;
216#ifdef ANDROID_BLOCK_NETWORK_IMAGE
217    jfieldID mBlockNetworkImage;
218#endif
219    jfieldID mBlockNetworkLoads;
220    jfieldID mJavaScriptEnabled;
221    jfieldID mPluginState;
222#if ENABLE(OFFLINE_WEB_APPLICATIONS)
223    jfieldID mAppCacheEnabled;
224    jfieldID mAppCachePath;
225    jfieldID mAppCacheMaxSize;
226#endif
227#if ENABLE(WORKERS)
228    jfieldID mWorkersEnabled;
229#endif
230    jfieldID mJavaScriptCanOpenWindowsAutomatically;
231    jfieldID mUseWideViewport;
232    jfieldID mSupportMultipleWindows;
233    jfieldID mShrinksStandaloneImagesToFit;
234    jfieldID mMaximumDecodedImageSize;
235    jfieldID mPrivateBrowsingEnabled;
236    jfieldID mSyntheticLinksEnabled;
237    jfieldID mUseDoubleTree;
238    jfieldID mPageCacheCapacity;
239    // Ordinal() method and value field for enums
240    jmethodID mOrdinal;
241    jfieldID  mTextSizeValue;
242
243#if ENABLE(DATABASE)
244    jfieldID mDatabaseEnabled;
245#endif
246#if ENABLE(DOM_STORAGE)
247    jfieldID mDomStorageEnabled;
248#endif
249    jfieldID mGeolocationEnabled;
250    jfieldID mGeolocationDatabasePath;
251    jfieldID mXSSAuditorEnabled;
252#if ENABLE(DATABASE) || ENABLE(DOM_STORAGE)
253    jfieldID mDatabasePath;
254    jfieldID mDatabasePathHasBeenSet;
255#endif
256#if ENABLE(WEB_AUTOFILL)
257    jfieldID mAutoFillEnabled;
258    jfieldID mAutoFillProfile;
259    jfieldID mAutoFillProfileFullName;
260    jfieldID mAutoFillProfileEmailAddress;
261    jfieldID mAutoFillProfileCompanyName;
262    jfieldID mAutoFillProfileAddressLine1;
263    jfieldID mAutoFillProfileAddressLine2;
264    jfieldID mAutoFillProfileCity;
265    jfieldID mAutoFillProfileState;
266    jfieldID mAutoFillProfileZipCode;
267    jfieldID mAutoFillProfileCountry;
268    jfieldID mAutoFillProfilePhoneNumber;
269#endif
270#if USE(CHROME_NETWORK_STACK)
271    jfieldID mOverrideCacheMode;
272#endif
273};
274
275static struct FieldIds* gFieldIds;
276
277// Note: This is moved from the old FrameAndroid.cpp
278static void recursiveCleanupForFullLayout(WebCore::RenderObject* obj)
279{
280    obj->setNeedsLayout(true, false);
281#ifdef ANDROID_LAYOUT
282    if (obj->isTable())
283        (static_cast<WebCore::RenderTable *>(obj))->clearSingleColumn();
284#endif
285    for (WebCore::RenderObject* n = obj->firstChild(); n; n = n->nextSibling())
286        recursiveCleanupForFullLayout(n);
287}
288
289#if ENABLE(WEB_AUTOFILL)
290inline string16 getStringFieldAsString16(JNIEnv* env, jobject autoFillProfile, jfieldID fieldId)
291{
292    jstring str = static_cast<jstring>(env->GetObjectField(autoFillProfile, fieldId));
293    return str ? jstringToString16(env, str) : string16();
294}
295
296void syncAutoFillProfile(JNIEnv* env, jobject autoFillProfile, WebAutofill* webAutofill)
297{
298    string16 fullName = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileFullName);
299    string16 emailAddress = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileEmailAddress);
300    string16 companyName = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileCompanyName);
301    string16 addressLine1 = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileAddressLine1);
302    string16 addressLine2 = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileAddressLine2);
303    string16 city = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileCity);
304    string16 state = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileState);
305    string16 zipCode = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileZipCode);
306    string16 country = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileCountry);
307    string16 phoneNumber = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfilePhoneNumber);
308
309    webAutofill->setProfile(fullName, emailAddress, companyName, addressLine1, addressLine2, city, state, zipCode, country, phoneNumber);
310}
311#endif
312
313class WebSettings {
314public:
315    static void Sync(JNIEnv* env, jobject obj, jint frame)
316    {
317        WebCore::Frame* pFrame = (WebCore::Frame*)frame;
318        LOG_ASSERT(pFrame, "%s must take a valid frame pointer!", __FUNCTION__);
319        WebCore::Settings* s = pFrame->settings();
320        if (!s)
321            return;
322        WebCore::CachedResourceLoader* cachedResourceLoader = pFrame->document()->cachedResourceLoader();
323
324#ifdef ANDROID_LAYOUT
325        jobject layout = env->GetObjectField(obj, gFieldIds->mLayoutAlgorithm);
326        WebCore::Settings::LayoutAlgorithm l = (WebCore::Settings::LayoutAlgorithm)
327                env->CallIntMethod(layout, gFieldIds->mOrdinal);
328        if (s->layoutAlgorithm() != l) {
329            s->setLayoutAlgorithm(l);
330            if (pFrame->document()) {
331                pFrame->document()->styleSelectorChanged(WebCore::RecalcStyleImmediately);
332                if (pFrame->document()->renderer()) {
333                    recursiveCleanupForFullLayout(pFrame->document()->renderer());
334                    LOG_ASSERT(pFrame->view(), "No view for this frame when trying to relayout");
335                    pFrame->view()->layout();
336                    // FIXME: This call used to scroll the page to put the focus into view.
337                    // It worked on the WebViewCore, but now scrolling is done outside of the
338                    // WebViewCore, on the UI side, so there needs to be a new way to do this.
339                    //pFrame->makeFocusVisible();
340                }
341            }
342        }
343#endif
344        jint textSize = env->GetIntField(obj, gFieldIds->mTextSize);
345        float zoomFactor = textSize / 100.0f;
346        if (pFrame->textZoomFactor() != zoomFactor)
347            pFrame->setTextZoomFactor(zoomFactor);
348
349        jstring str = (jstring)env->GetObjectField(obj, gFieldIds->mStandardFontFamily);
350        s->setStandardFontFamily(jstringToWtfString(env, str));
351
352        str = (jstring)env->GetObjectField(obj, gFieldIds->mFixedFontFamily);
353        s->setFixedFontFamily(jstringToWtfString(env, str));
354
355        str = (jstring)env->GetObjectField(obj, gFieldIds->mSansSerifFontFamily);
356        s->setSansSerifFontFamily(jstringToWtfString(env, str));
357
358        str = (jstring)env->GetObjectField(obj, gFieldIds->mSerifFontFamily);
359        s->setSerifFontFamily(jstringToWtfString(env, str));
360
361        str = (jstring)env->GetObjectField(obj, gFieldIds->mCursiveFontFamily);
362        s->setCursiveFontFamily(jstringToWtfString(env, str));
363
364        str = (jstring)env->GetObjectField(obj, gFieldIds->mFantasyFontFamily);
365        s->setFantasyFontFamily(jstringToWtfString(env, str));
366
367        str = (jstring)env->GetObjectField(obj, gFieldIds->mDefaultTextEncoding);
368        s->setDefaultTextEncodingName(jstringToWtfString(env, str));
369
370        str = (jstring)env->GetObjectField(obj, gFieldIds->mUserAgent);
371        WebFrame::getWebFrame(pFrame)->setUserAgent(jstringToWtfString(env, str));
372#if USE(CHROME_NETWORK_STACK)
373        WebViewCore::getWebViewCore(pFrame->view())->setWebRequestContextUserAgent();
374
375        jint cacheMode = env->GetIntField(obj, gFieldIds->mOverrideCacheMode);
376        WebViewCore::getWebViewCore(pFrame->view())->setWebRequestContextCacheMode(cacheMode);
377
378        str = (jstring)env->GetObjectField(obj, gFieldIds->mAcceptLanguage);
379        WebRequestContext::setAcceptLanguage(jstringToWtfString(env, str));
380#endif
381
382        jint size = env->GetIntField(obj, gFieldIds->mMinimumFontSize);
383        s->setMinimumFontSize(size);
384
385        size = env->GetIntField(obj, gFieldIds->mMinimumLogicalFontSize);
386        s->setMinimumLogicalFontSize(size);
387
388        size = env->GetIntField(obj, gFieldIds->mDefaultFontSize);
389        s->setDefaultFontSize(size);
390
391        size = env->GetIntField(obj, gFieldIds->mDefaultFixedFontSize);
392        s->setDefaultFixedFontSize(size);
393
394        jboolean flag = env->GetBooleanField(obj, gFieldIds->mLoadsImagesAutomatically);
395        s->setLoadsImagesAutomatically(flag);
396        if (flag)
397            cachedResourceLoader->setAutoLoadImages(true);
398
399#ifdef ANDROID_BLOCK_NETWORK_IMAGE
400        flag = env->GetBooleanField(obj, gFieldIds->mBlockNetworkImage);
401        s->setBlockNetworkImage(flag);
402        if(!flag)
403            cachedResourceLoader->setBlockNetworkImage(false);
404#endif
405        flag = env->GetBooleanField(obj, gFieldIds->mBlockNetworkLoads);
406        WebFrame* webFrame = WebFrame::getWebFrame(pFrame);
407        webFrame->setBlockNetworkLoads(flag);
408
409        flag = env->GetBooleanField(obj, gFieldIds->mJavaScriptEnabled);
410        s->setJavaScriptEnabled(flag);
411
412        // ON = 0
413        // ON_DEMAND = 1
414        // OFF = 2
415        jobject pluginState = env->GetObjectField(obj, gFieldIds->mPluginState);
416        int state = env->CallIntMethod(pluginState, gFieldIds->mOrdinal);
417        s->setPluginsEnabled(state < 2);
418#ifdef ANDROID_PLUGINS
419        s->setPluginsOnDemand(state == 1);
420#endif
421
422#if ENABLE(OFFLINE_WEB_APPLICATIONS)
423        flag = env->GetBooleanField(obj, gFieldIds->mAppCacheEnabled);
424        s->setOfflineWebApplicationCacheEnabled(flag);
425        str = (jstring)env->GetObjectField(obj, gFieldIds->mAppCachePath);
426        if (str) {
427            String path = jstringToWtfString(env, str);
428            if (path.length() && cacheStorage().cacheDirectory().isNull()) {
429                cacheStorage().setCacheDirectory(path);
430                // This database is created on the first load. If the file
431                // doesn't exist, we create it and set its permissions. The
432                // filename must match that in ApplicationCacheStorage.cpp.
433                String filename = pathByAppendingComponent(path, "ApplicationCache.db");
434                int fd = open(filename.utf8().data(), O_CREAT | O_EXCL, permissionFlags660);
435                if (fd >= 0)
436                    close(fd);
437            }
438        }
439        jlong maxsize = env->GetLongField(obj, gFieldIds->mAppCacheMaxSize);
440        cacheStorage().setMaximumSize(maxsize);
441#endif
442
443        flag = env->GetBooleanField(obj, gFieldIds->mJavaScriptCanOpenWindowsAutomatically);
444        s->setJavaScriptCanOpenWindowsAutomatically(flag);
445
446#ifdef ANDROID_LAYOUT
447        flag = env->GetBooleanField(obj, gFieldIds->mUseWideViewport);
448        s->setUseWideViewport(flag);
449#endif
450
451#ifdef ANDROID_MULTIPLE_WINDOWS
452        flag = env->GetBooleanField(obj, gFieldIds->mSupportMultipleWindows);
453        s->setSupportMultipleWindows(flag);
454#endif
455        flag = env->GetBooleanField(obj, gFieldIds->mShrinksStandaloneImagesToFit);
456        s->setShrinksStandaloneImagesToFit(flag);
457        jlong maxImage = env->GetLongField(obj, gFieldIds->mMaximumDecodedImageSize);
458        // Since in ImageSourceAndroid.cpp, the image will always not exceed
459        // MAX_SIZE_BEFORE_SUBSAMPLE, there's no need to pass the max value to
460        // WebCore, which checks (image_width * image_height * 4) as an
461        // estimation against the max value, which is done in CachedImage.cpp.
462        // And there're cases where the decoded image size will not
463        // exceed the max, but the WebCore estimation will.  So the following
464        // code is commented out to fix those cases.
465        // if (maxImage == 0)
466        //    maxImage = computeMaxBitmapSizeForCache();
467        s->setMaximumDecodedImageSize(maxImage);
468
469        flag = env->GetBooleanField(obj, gFieldIds->mPrivateBrowsingEnabled);
470        s->setPrivateBrowsingEnabled(flag);
471
472        flag = env->GetBooleanField(obj, gFieldIds->mSyntheticLinksEnabled);
473        s->setDefaultFormatDetection(flag);
474        s->setFormatDetectionAddress(flag);
475        s->setFormatDetectionEmail(flag);
476        s->setFormatDetectionTelephone(flag);
477#if ENABLE(DATABASE)
478        flag = env->GetBooleanField(obj, gFieldIds->mDatabaseEnabled);
479        WebCore::Database::setIsAvailable(flag);
480
481        flag = env->GetBooleanField(obj, gFieldIds->mDatabasePathHasBeenSet);
482        if (flag) {
483            // If the user has set the database path, sync it to the DatabaseTracker.
484            str = (jstring)env->GetObjectField(obj, gFieldIds->mDatabasePath);
485            if (str) {
486                String path = jstringToWtfString(env, str);
487                DatabaseTracker::tracker().setDatabaseDirectoryPath(path);
488                // This database is created when the first HTML5 Database object is
489                // instantiated. If the file doesn't exist, we create it and set its
490                // permissions. The filename must match that in
491                // DatabaseTracker.cpp.
492                String filename = SQLiteFileSystem::appendDatabaseFileNameToPath(path, "Databases.db");
493                int fd = open(filename.utf8().data(), O_CREAT | O_EXCL, permissionFlags660);
494                if (fd >= 0)
495                    close(fd);
496            }
497        }
498#endif
499#if ENABLE(DOM_STORAGE)
500        flag = env->GetBooleanField(obj, gFieldIds->mDomStorageEnabled);
501        s->setLocalStorageEnabled(flag);
502        str = (jstring)env->GetObjectField(obj, gFieldIds->mDatabasePath);
503        if (str) {
504            WTF::String localStorageDatabasePath = jstringToWtfString(env,str);
505            if (localStorageDatabasePath.length()) {
506                localStorageDatabasePath = WebCore::pathByAppendingComponent(
507                        localStorageDatabasePath, "localstorage");
508                // We need 770 for folders
509                mkdir(localStorageDatabasePath.utf8().data(),
510                        permissionFlags660 | S_IXUSR | S_IXGRP);
511                s->setLocalStorageDatabasePath(localStorageDatabasePath);
512            }
513        }
514#endif
515
516        flag = env->GetBooleanField(obj, gFieldIds->mGeolocationEnabled);
517        GeolocationPermissions::setAlwaysDeny(!flag);
518        str = (jstring)env->GetObjectField(obj, gFieldIds->mGeolocationDatabasePath);
519        if (str) {
520            String path = jstringToWtfString(env, str);
521            GeolocationPermissions::setDatabasePath(path);
522            GeolocationPositionCache::instance()->setDatabasePath(path);
523            // This database is created when the first Geolocation object is
524            // instantiated. If the file doesn't exist, we create it and set its
525            // permissions. The filename must match that in
526            // GeolocationPositionCache.cpp.
527            String filename = SQLiteFileSystem::appendDatabaseFileNameToPath(path, "CachedGeoposition.db");
528            int fd = open(filename.utf8().data(), O_CREAT | O_EXCL, permissionFlags660);
529            if (fd >= 0)
530                close(fd);
531        }
532
533        flag = env->GetBooleanField(obj, gFieldIds->mXSSAuditorEnabled);
534        s->setXSSAuditorEnabled(flag);
535
536        size = env->GetIntField(obj, gFieldIds->mPageCacheCapacity);
537        if (size > 0) {
538            s->setUsesPageCache(true);
539            WebCore::pageCache()->setCapacity(size);
540        } else
541            s->setUsesPageCache(false);
542
543#if ENABLE(WEB_AUTOFILL)
544        flag = env->GetBooleanField(obj, gFieldIds->mAutoFillEnabled);
545        // TODO: This updates the Settings WebCore side with the user's
546        // preference for autofill and will stop WebCore making requests
547        // into the chromium autofill code. That code in Chromium also has
548        // a notion of being enabled/disabled that gets read from the users
549        // preferences. At the moment, it's hardcoded to true on Android
550        // (see chrome/browser/autofill/autofill_manager.cc:405). This
551        // setting should probably be synced into Chromium also.
552
553        s->setAutoFillEnabled(flag);
554
555        if (flag) {
556            EditorClientAndroid* editorC = static_cast<EditorClientAndroid*>(pFrame->page()->editorClient());
557            WebAutofill* webAutofill = editorC->getAutofill();
558            // Set the active AutofillProfile data.
559            jobject autoFillProfile = env->GetObjectField(obj, gFieldIds->mAutoFillProfile);
560            if (autoFillProfile)
561                syncAutoFillProfile(env, autoFillProfile, webAutofill);
562            else {
563                // The autofill profile is null. We need to tell Chromium about this because
564                // this may be because the user just deleted their profile but left the
565                // autofill feature setting enabled.
566                webAutofill->clearProfiles();
567            }
568        }
569#endif
570
571        // This is required to enable the XMLTreeViewer when loading an XML document that
572        // has no style attached to it. http://trac.webkit.org/changeset/79799
573        s->setDeveloperExtrasEnabled(true);
574    }
575};
576
577
578//-------------------------------------------------------------
579// JNI registration
580//-------------------------------------------------------------
581
582static JNINativeMethod gWebSettingsMethods[] = {
583    { "nativeSync", "(I)V",
584        (void*) WebSettings::Sync }
585};
586
587int registerWebSettings(JNIEnv* env)
588{
589    jclass clazz = env->FindClass("android/webkit/WebSettings");
590    LOG_ASSERT(clazz, "Unable to find class WebSettings!");
591    gFieldIds = new FieldIds(env, clazz);
592    env->DeleteLocalRef(clazz);
593    return jniRegisterNativeMethods(env, "android/webkit/WebSettings",
594            gWebSettingsMethods, NELEM(gWebSettingsMethods));
595}
596
597}
598