Home | History | Annotate | Download | only in jni
      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 "DatabaseTracker.h"
     33 #include "DocLoader.h"
     34 #include "Document.h"
     35 #include "Frame.h"
     36 #include "FrameLoader.h"
     37 #include "FrameView.h"
     38 #include "GeolocationPermissions.h"
     39 #include "GeolocationPositionCache.h"
     40 #include "Page.h"
     41 #include "PageCache.h"
     42 #include "RenderTable.h"
     43 #include "Settings.h"
     44 #include "WebCoreFrameBridge.h"
     45 #include "WebCoreJni.h"
     46 #if USE(V8)
     47 #include "WorkerContextExecutionProxy.h"
     48 #endif
     49 
     50 #include <JNIHelp.h>
     51 #include <utils/misc.h>
     52 
     53 namespace android {
     54 
     55 struct FieldIds {
     56     FieldIds(JNIEnv* env, jclass clazz) {
     57         mLayoutAlgorithm = env->GetFieldID(clazz, "mLayoutAlgorithm",
     58                 "Landroid/webkit/WebSettings$LayoutAlgorithm;");
     59         mTextSize = env->GetFieldID(clazz, "mTextSize",
     60                 "Landroid/webkit/WebSettings$TextSize;");
     61         mStandardFontFamily = env->GetFieldID(clazz, "mStandardFontFamily",
     62                 "Ljava/lang/String;");
     63         mFixedFontFamily = env->GetFieldID(clazz, "mFixedFontFamily",
     64                 "Ljava/lang/String;");
     65         mSansSerifFontFamily = env->GetFieldID(clazz, "mSansSerifFontFamily",
     66                 "Ljava/lang/String;");
     67         mSerifFontFamily = env->GetFieldID(clazz, "mSerifFontFamily",
     68                 "Ljava/lang/String;");
     69         mCursiveFontFamily = env->GetFieldID(clazz, "mCursiveFontFamily",
     70                 "Ljava/lang/String;");
     71         mFantasyFontFamily = env->GetFieldID(clazz, "mFantasyFontFamily",
     72                 "Ljava/lang/String;");
     73         mDefaultTextEncoding = env->GetFieldID(clazz, "mDefaultTextEncoding",
     74                 "Ljava/lang/String;");
     75         mUserAgent = env->GetFieldID(clazz, "mUserAgent",
     76                 "Ljava/lang/String;");
     77         mMinimumFontSize = env->GetFieldID(clazz, "mMinimumFontSize", "I");
     78         mMinimumLogicalFontSize = env->GetFieldID(clazz, "mMinimumLogicalFontSize", "I");
     79         mDefaultFontSize = env->GetFieldID(clazz, "mDefaultFontSize", "I");
     80         mDefaultFixedFontSize = env->GetFieldID(clazz, "mDefaultFixedFontSize", "I");
     81         mLoadsImagesAutomatically = env->GetFieldID(clazz, "mLoadsImagesAutomatically", "Z");
     82 #ifdef ANDROID_BLOCK_NETWORK_IMAGE
     83         mBlockNetworkImage = env->GetFieldID(clazz, "mBlockNetworkImage", "Z");
     84 #endif
     85         mJavaScriptEnabled = env->GetFieldID(clazz, "mJavaScriptEnabled", "Z");
     86         mPluginState = env->GetFieldID(clazz, "mPluginState",
     87                 "Landroid/webkit/WebSettings$PluginState;");
     88 #if ENABLE(DATABASE)
     89         mDatabaseEnabled = env->GetFieldID(clazz, "mDatabaseEnabled", "Z");
     90 #endif
     91 #if ENABLE(DOM_STORAGE)
     92         mDomStorageEnabled = env->GetFieldID(clazz, "mDomStorageEnabled", "Z");
     93 #endif
     94 #if ENABLE(DATABASE) || ENABLE(DOM_STORAGE)
     95         // The databases saved to disk for both the SQL and DOM Storage APIs are stored
     96         // in the same base directory.
     97         mDatabasePath = env->GetFieldID(clazz, "mDatabasePath", "Ljava/lang/String;");
     98         mDatabasePathHasBeenSet = env->GetFieldID(clazz, "mDatabasePathHasBeenSet", "Z");
     99 #endif
    100 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
    101         mAppCacheEnabled = env->GetFieldID(clazz, "mAppCacheEnabled", "Z");
    102         mAppCachePath = env->GetFieldID(clazz, "mAppCachePath", "Ljava/lang/String;");
    103         mAppCacheMaxSize = env->GetFieldID(clazz, "mAppCacheMaxSize", "J");
    104 #endif
    105 #if ENABLE(WORKERS)
    106         mWorkersEnabled = env->GetFieldID(clazz, "mWorkersEnabled", "Z");
    107 #endif
    108         mGeolocationEnabled = env->GetFieldID(clazz, "mGeolocationEnabled", "Z");
    109         mGeolocationDatabasePath = env->GetFieldID(clazz, "mGeolocationDatabasePath", "Ljava/lang/String;");
    110         mJavaScriptCanOpenWindowsAutomatically = env->GetFieldID(clazz,
    111                 "mJavaScriptCanOpenWindowsAutomatically", "Z");
    112         mUseWideViewport = env->GetFieldID(clazz, "mUseWideViewport", "Z");
    113         mSupportMultipleWindows = env->GetFieldID(clazz, "mSupportMultipleWindows", "Z");
    114         mShrinksStandaloneImagesToFit = env->GetFieldID(clazz, "mShrinksStandaloneImagesToFit", "Z");
    115         mUseDoubleTree = env->GetFieldID(clazz, "mUseDoubleTree", "Z");
    116         mPageCacheCapacity = env->GetFieldID(clazz, "mPageCacheCapacity", "I");
    117 
    118         LOG_ASSERT(mLayoutAlgorithm, "Could not find field mLayoutAlgorithm");
    119         LOG_ASSERT(mTextSize, "Could not find field mTextSize");
    120         LOG_ASSERT(mStandardFontFamily, "Could not find field mStandardFontFamily");
    121         LOG_ASSERT(mFixedFontFamily, "Could not find field mFixedFontFamily");
    122         LOG_ASSERT(mSansSerifFontFamily, "Could not find field mSansSerifFontFamily");
    123         LOG_ASSERT(mSerifFontFamily, "Could not find field mSerifFontFamily");
    124         LOG_ASSERT(mCursiveFontFamily, "Could not find field mCursiveFontFamily");
    125         LOG_ASSERT(mFantasyFontFamily, "Could not find field mFantasyFontFamily");
    126         LOG_ASSERT(mDefaultTextEncoding, "Could not find field mDefaultTextEncoding");
    127         LOG_ASSERT(mUserAgent, "Could not find field mUserAgent");
    128         LOG_ASSERT(mMinimumFontSize, "Could not find field mMinimumFontSize");
    129         LOG_ASSERT(mMinimumLogicalFontSize, "Could not find field mMinimumLogicalFontSize");
    130         LOG_ASSERT(mDefaultFontSize, "Could not find field mDefaultFontSize");
    131         LOG_ASSERT(mDefaultFixedFontSize, "Could not find field mDefaultFixedFontSize");
    132         LOG_ASSERT(mLoadsImagesAutomatically, "Could not find field mLoadsImagesAutomatically");
    133 #ifdef ANDROID_BLOCK_NETWORK_IMAGE
    134         LOG_ASSERT(mBlockNetworkImage, "Could not find field mBlockNetworkImage");
    135 #endif
    136         LOG_ASSERT(mJavaScriptEnabled, "Could not find field mJavaScriptEnabled");
    137         LOG_ASSERT(mPluginState, "Could not find field mPluginState");
    138 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
    139         LOG_ASSERT(mAppCacheEnabled, "Could not find field mAppCacheEnabled");
    140         LOG_ASSERT(mAppCachePath, "Could not find field mAppCachePath");
    141         LOG_ASSERT(mAppCacheMaxSize, "Could not find field mAppCacheMaxSize");
    142 #endif
    143 #if ENABLE(WORKERS)
    144         LOG_ASSERT(mWorkersEnabled, "Could not find field mWorkersEnabled");
    145 #endif
    146         LOG_ASSERT(mJavaScriptCanOpenWindowsAutomatically,
    147                 "Could not find field mJavaScriptCanOpenWindowsAutomatically");
    148         LOG_ASSERT(mUseWideViewport, "Could not find field mUseWideViewport");
    149         LOG_ASSERT(mSupportMultipleWindows, "Could not find field mSupportMultipleWindows");
    150         LOG_ASSERT(mShrinksStandaloneImagesToFit, "Could not find field mShrinksStandaloneImagesToFit");
    151         LOG_ASSERT(mUseDoubleTree, "Could not find field mUseDoubleTree");
    152         LOG_ASSERT(mPageCacheCapacity, "Could not find field mPageCacheCapacity");
    153 
    154         jclass c = env->FindClass("java/lang/Enum");
    155         LOG_ASSERT(c, "Could not find Enum class!");
    156         mOrdinal = env->GetMethodID(c, "ordinal", "()I");
    157         LOG_ASSERT(mOrdinal, "Could not find method ordinal");
    158         c = env->FindClass("android/webkit/WebSettings$TextSize");
    159         LOG_ASSERT(c, "Could not find TextSize enum");
    160         mTextSizeValue = env->GetFieldID(c, "value", "I");
    161     }
    162 
    163     // Field ids
    164     jfieldID mLayoutAlgorithm;
    165     jfieldID mTextSize;
    166     jfieldID mStandardFontFamily;
    167     jfieldID mFixedFontFamily;
    168     jfieldID mSansSerifFontFamily;
    169     jfieldID mSerifFontFamily;
    170     jfieldID mCursiveFontFamily;
    171     jfieldID mFantasyFontFamily;
    172     jfieldID mDefaultTextEncoding;
    173     jfieldID mUserAgent;
    174     jfieldID mMinimumFontSize;
    175     jfieldID mMinimumLogicalFontSize;
    176     jfieldID mDefaultFontSize;
    177     jfieldID mDefaultFixedFontSize;
    178     jfieldID mLoadsImagesAutomatically;
    179 #ifdef ANDROID_BLOCK_NETWORK_IMAGE
    180     jfieldID mBlockNetworkImage;
    181 #endif
    182     jfieldID mJavaScriptEnabled;
    183     jfieldID mPluginState;
    184 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
    185     jfieldID mAppCacheEnabled;
    186     jfieldID mAppCachePath;
    187     jfieldID mAppCacheMaxSize;
    188 #endif
    189 #if ENABLE(WORKERS)
    190     jfieldID mWorkersEnabled;
    191 #endif
    192     jfieldID mJavaScriptCanOpenWindowsAutomatically;
    193     jfieldID mUseWideViewport;
    194     jfieldID mSupportMultipleWindows;
    195     jfieldID mShrinksStandaloneImagesToFit;
    196     jfieldID mUseDoubleTree;
    197     jfieldID mPageCacheCapacity;
    198     // Ordinal() method and value field for enums
    199     jmethodID mOrdinal;
    200     jfieldID  mTextSizeValue;
    201 
    202 #if ENABLE(DATABASE)
    203     jfieldID mDatabaseEnabled;
    204 #endif
    205 #if ENABLE(DOM_STORAGE)
    206     jfieldID mDomStorageEnabled;
    207 #endif
    208     jfieldID mGeolocationEnabled;
    209     jfieldID mGeolocationDatabasePath;
    210 #if ENABLE(DATABASE) || ENABLE(DOM_STORAGE)
    211     jfieldID mDatabasePath;
    212     jfieldID mDatabasePathHasBeenSet;
    213 #endif
    214 };
    215 
    216 static struct FieldIds* gFieldIds;
    217 
    218 // Note: This is moved from the old FrameAndroid.cpp
    219 static void recursiveCleanupForFullLayout(WebCore::RenderObject* obj)
    220 {
    221     obj->setNeedsLayout(true, false);
    222 #ifdef ANDROID_LAYOUT
    223     if (obj->isTable())
    224         (static_cast<WebCore::RenderTable *>(obj))->clearSingleColumn();
    225 #endif
    226     for (WebCore::RenderObject* n = obj->firstChild(); n; n = n->nextSibling())
    227         recursiveCleanupForFullLayout(n);
    228 }
    229 
    230 class WebSettings {
    231 public:
    232     static void Sync(JNIEnv* env, jobject obj, jint frame)
    233     {
    234         WebCore::Frame* pFrame = (WebCore::Frame*)frame;
    235         LOG_ASSERT(pFrame, "%s must take a valid frame pointer!", __FUNCTION__);
    236         WebCore::Settings* s = pFrame->settings();
    237         if (!s)
    238             return;
    239         WebCore::DocLoader* docLoader = pFrame->document()->docLoader();
    240 
    241 #ifdef ANDROID_LAYOUT
    242         jobject layout = env->GetObjectField(obj, gFieldIds->mLayoutAlgorithm);
    243         WebCore::Settings::LayoutAlgorithm l = (WebCore::Settings::LayoutAlgorithm)
    244                 env->CallIntMethod(layout, gFieldIds->mOrdinal);
    245         if (s->layoutAlgorithm() != l) {
    246             s->setLayoutAlgorithm(l);
    247             if (pFrame->document()) {
    248                 pFrame->document()->updateStyleSelector();
    249                 if (pFrame->document()->renderer()) {
    250                     recursiveCleanupForFullLayout(pFrame->document()->renderer());
    251                     LOG_ASSERT(pFrame->view(), "No view for this frame when trying to relayout");
    252                     pFrame->view()->layout();
    253                     // FIXME: This call used to scroll the page to put the focus into view.
    254                     // It worked on the WebViewCore, but now scrolling is done outside of the
    255                     // WebViewCore, on the UI side, so there needs to be a new way to do this.
    256                     //pFrame->makeFocusVisible();
    257                 }
    258             }
    259         }
    260 #endif
    261         jobject textSize = env->GetObjectField(obj, gFieldIds->mTextSize);
    262         float zoomFactor = env->GetIntField(textSize, gFieldIds->mTextSizeValue) / 100.0f;
    263         if (pFrame->zoomFactor() != zoomFactor)
    264             pFrame->setZoomFactor(zoomFactor, /*isTextOnly*/true);
    265 
    266         jstring str = (jstring)env->GetObjectField(obj, gFieldIds->mStandardFontFamily);
    267         s->setStandardFontFamily(to_string(env, str));
    268 
    269         str = (jstring)env->GetObjectField(obj, gFieldIds->mFixedFontFamily);
    270         s->setFixedFontFamily(to_string(env, str));
    271 
    272         str = (jstring)env->GetObjectField(obj, gFieldIds->mSansSerifFontFamily);
    273         s->setSansSerifFontFamily(to_string(env, str));
    274 
    275         str = (jstring)env->GetObjectField(obj, gFieldIds->mSerifFontFamily);
    276         s->setSerifFontFamily(to_string(env, str));
    277 
    278         str = (jstring)env->GetObjectField(obj, gFieldIds->mCursiveFontFamily);
    279         s->setCursiveFontFamily(to_string(env, str));
    280 
    281         str = (jstring)env->GetObjectField(obj, gFieldIds->mFantasyFontFamily);
    282         s->setFantasyFontFamily(to_string(env, str));
    283 
    284         str = (jstring)env->GetObjectField(obj, gFieldIds->mDefaultTextEncoding);
    285         s->setDefaultTextEncodingName(to_string(env, str));
    286 
    287         str = (jstring)env->GetObjectField(obj, gFieldIds->mUserAgent);
    288         WebFrame::getWebFrame(pFrame)->setUserAgent(to_string(env, str));
    289 
    290         jint size = env->GetIntField(obj, gFieldIds->mMinimumFontSize);
    291         s->setMinimumFontSize(size);
    292 
    293         size = env->GetIntField(obj, gFieldIds->mMinimumLogicalFontSize);
    294         s->setMinimumLogicalFontSize(size);
    295 
    296         size = env->GetIntField(obj, gFieldIds->mDefaultFontSize);
    297         s->setDefaultFontSize(size);
    298 
    299         size = env->GetIntField(obj, gFieldIds->mDefaultFixedFontSize);
    300         s->setDefaultFixedFontSize(size);
    301 
    302         jboolean flag = env->GetBooleanField(obj, gFieldIds->mLoadsImagesAutomatically);
    303         s->setLoadsImagesAutomatically(flag);
    304         if (flag)
    305             docLoader->setAutoLoadImages(true);
    306 
    307 #ifdef ANDROID_BLOCK_NETWORK_IMAGE
    308         flag = env->GetBooleanField(obj, gFieldIds->mBlockNetworkImage);
    309         s->setBlockNetworkImage(flag);
    310         if(!flag)
    311             docLoader->setBlockNetworkImage(false);
    312 #endif
    313 
    314         flag = env->GetBooleanField(obj, gFieldIds->mJavaScriptEnabled);
    315         s->setJavaScriptEnabled(flag);
    316 
    317         // ON = 0
    318         // ON_DEMAND = 1
    319         // OFF = 2
    320         jobject pluginState = env->GetObjectField(obj, gFieldIds->mPluginState);
    321         int state = env->CallIntMethod(pluginState, gFieldIds->mOrdinal);
    322         s->setPluginsEnabled(state < 2);
    323 #ifdef ANDROID_PLUGINS
    324         s->setPluginsOnDemand(state == 1);
    325 #endif
    326 
    327 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
    328         flag = env->GetBooleanField(obj, gFieldIds->mAppCacheEnabled);
    329         s->setOfflineWebApplicationCacheEnabled(flag);
    330         str = (jstring)env->GetObjectField(obj, gFieldIds->mAppCachePath);
    331         if (str) {
    332             WebCore::String path = to_string(env, str);
    333             if (path.length() && WebCore::cacheStorage().cacheDirectory().isNull()) {
    334                 WebCore::cacheStorage().setCacheDirectory(path);
    335             }
    336         }
    337         jlong maxsize = env->GetIntField(obj, gFieldIds->mAppCacheMaxSize);
    338         WebCore::cacheStorage().setMaximumSize(maxsize);
    339 #endif
    340 
    341         flag = env->GetBooleanField(obj, gFieldIds->mJavaScriptCanOpenWindowsAutomatically);
    342         s->setJavaScriptCanOpenWindowsAutomatically(flag);
    343 
    344 #ifdef ANDROID_LAYOUT
    345         flag = env->GetBooleanField(obj, gFieldIds->mUseWideViewport);
    346         s->setUseWideViewport(flag);
    347 #endif
    348 
    349 #ifdef ANDROID_MULTIPLE_WINDOWS
    350         flag = env->GetBooleanField(obj, gFieldIds->mSupportMultipleWindows);
    351         s->setSupportMultipleWindows(flag);
    352 #endif
    353         flag = env->GetBooleanField(obj, gFieldIds->mShrinksStandaloneImagesToFit);
    354         s->setShrinksStandaloneImagesToFit(flag);
    355 #if ENABLE(DATABASE)
    356         flag = env->GetBooleanField(obj, gFieldIds->mDatabaseEnabled);
    357         s->setDatabasesEnabled(flag);
    358 
    359         flag = env->GetBooleanField(obj, gFieldIds->mDatabasePathHasBeenSet);
    360         if (flag) {
    361             // If the user has set the database path, sync it to the DatabaseTracker.
    362             str = (jstring)env->GetObjectField(obj, gFieldIds->mDatabasePath);
    363             if (str)
    364                 WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(to_string(env, str));
    365         }
    366 #endif
    367 #if ENABLE(DOM_STORAGE)
    368         flag = env->GetBooleanField(obj, gFieldIds->mDomStorageEnabled);
    369         s->setLocalStorageEnabled(flag);
    370         str = (jstring)env->GetObjectField(obj, gFieldIds->mDatabasePath);
    371         if (str) {
    372             WebCore::String localStorageDatabasePath = to_string(env,str);
    373             if (localStorageDatabasePath.length()) {
    374                 s->setLocalStorageDatabasePath(localStorageDatabasePath);
    375             }
    376         }
    377 #endif
    378 
    379         flag = env->GetBooleanField(obj, gFieldIds->mGeolocationEnabled);
    380         GeolocationPermissions::setAlwaysDeny(!flag);
    381         str = (jstring)env->GetObjectField(obj, gFieldIds->mGeolocationDatabasePath);
    382         if (str) {
    383             GeolocationPermissions::setDatabasePath(to_string(env,str));
    384             WebCore::GeolocationPositionCache::setDatabasePath(to_string(env,str));
    385         }
    386 
    387         size = env->GetIntField(obj, gFieldIds->mPageCacheCapacity);
    388         if (size > 0) {
    389             s->setUsesPageCache(true);
    390             WebCore::pageCache()->setCapacity(size);
    391         } else
    392             s->setUsesPageCache(false);
    393     }
    394 };
    395 
    396 //-------------------------------------------------------------
    397 // JNI registration
    398 //-------------------------------------------------------------
    399 
    400 static JNINativeMethod gWebSettingsMethods[] = {
    401     { "nativeSync", "(I)V",
    402         (void*) WebSettings::Sync }
    403 };
    404 
    405 int register_websettings(JNIEnv* env)
    406 {
    407     jclass clazz = env->FindClass("android/webkit/WebSettings");
    408     LOG_ASSERT(clazz, "Unable to find class WebSettings!");
    409     gFieldIds = new FieldIds(env, clazz);
    410     return jniRegisterNativeMethods(env, "android/webkit/WebSettings",
    411             gWebSettingsMethods, NELEM(gWebSettingsMethods));
    412 }
    413 
    414 }
    415