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