1 /* 2 Copyright (C) 2009-2010 ProFUSION embedded systems 3 Copyright (C) 2009-2010 Samsung Electronics 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Library General Public 7 License as published by the Free Software Foundation; either 8 version 2 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public License 16 along with this library; see the file COPYING.LIB. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 21 #include "config.h" 22 #include "ewk_settings.h" 23 24 #include "EWebKit.h" 25 #if ENABLE(DATABASE) 26 #include "DatabaseTracker.h" 27 #endif 28 #include "IconDatabase.h" 29 #include "Image.h" 30 #include "IntSize.h" 31 #include "KURL.h" 32 #include "MemoryCache.h" 33 #include "ewk_private.h" 34 35 #include <Eina.h> 36 #include <eina_safety_checks.h> 37 #include <errno.h> 38 #include <string.h> 39 #include <sys/stat.h> 40 #include <sys/types.h> 41 #include <sys/utsname.h> 42 #include <unistd.h> 43 #include <wtf/text/CString.h> 44 #include <wtf/text/StringConcatenate.h> 45 46 #if USE(SOUP) 47 #include "ResourceHandle.h" 48 #include <libsoup/soup.h> 49 #endif 50 51 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 52 #include "appcache/ApplicationCacheStorage.h" 53 54 static const char* _ewk_cache_directory_path = 0; 55 #endif 56 57 static const char* _ewk_default_web_database_path = 0; 58 static const char* _ewk_icon_database_path = 0; 59 static uint64_t _ewk_default_web_database_quota = 1 * 1024 * 1024; 60 61 static WTF::String _ewk_settings_webkit_platform_get() 62 { 63 WTF::String ua_platform; 64 #if PLATFORM(X11) 65 ua_platform = "X11"; 66 #else 67 ua_platform = "Unknown"; 68 #endif 69 return ua_platform; 70 } 71 72 static WTF::String _ewk_settings_webkit_os_version_get() 73 { 74 WTF::String ua_os_version; 75 struct utsname name; 76 77 if (uname(&name) != -1) 78 ua_os_version = WTF::String(name.sysname) + " " + WTF::String(name.machine); 79 else 80 ua_os_version = "Unknown"; 81 82 return ua_os_version; 83 } 84 85 /** 86 * Returns the default quota for Web Database databases. By default 87 * this value is 1MB. 88 * 89 * @return the current default database quota in bytes 90 */ 91 uint64_t ewk_settings_web_database_default_quota_get(void) 92 { 93 return _ewk_default_web_database_quota; 94 } 95 96 /** 97 * Sets the current path to the directory WebKit will write Web 98 * Database databases. 99 * 100 * @param path the new database directory path 101 */ 102 void ewk_settings_web_database_path_set(const char *path) 103 { 104 #if ENABLE(DATABASE) 105 WTF::String corePath = WTF::String::fromUTF8(path); 106 WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(corePath); 107 if (!_ewk_default_web_database_path) 108 _ewk_default_web_database_path = eina_stringshare_add(corePath.utf8().data()); 109 else 110 eina_stringshare_replace(&_ewk_default_web_database_path, corePath.utf8().data()); 111 112 #endif 113 } 114 115 /** 116 * Returns directory path where web database is stored. 117 * 118 * This is guaranteed to be eina_stringshare, so whenever possible 119 * save yourself some cpu cycles and use eina_stringshare_ref() 120 * instead of eina_stringshare_add() or strdup(). 121 * 122 * @return database path or @c 0 if none or web database is not supported 123 */ 124 const char *ewk_settings_web_database_path_get(void) 125 { 126 #if ENABLE(DATABASE) 127 return _ewk_default_web_database_path; 128 #else 129 return 0; 130 #endif 131 } 132 133 /** 134 * Sets directory where to store icon database, opening or closing database. 135 * 136 * @param directory where to store icon database, must be 137 * write-able, if @c 0 is given, then database is closed 138 * 139 * @return @c EINA_TRUE on success, @c EINA_FALSE on errors 140 */ 141 Eina_Bool ewk_settings_icon_database_path_set(const char *directory) 142 { 143 WebCore::IconDatabase::delayDatabaseCleanup(); 144 145 if (directory) { 146 struct stat st; 147 148 if (stat(directory, &st)) { 149 ERR("could not stat(%s): %s", directory, strerror(errno)); 150 return EINA_FALSE; 151 } 152 153 if (!S_ISDIR(st.st_mode)) { 154 ERR("not a directory: %s", directory); 155 return EINA_FALSE; 156 } 157 158 if (access(directory, R_OK | W_OK)) { 159 ERR("could not access directory '%s' for read and write: %s", 160 directory, strerror(errno)); 161 return EINA_FALSE; 162 } 163 164 WebCore::iconDatabase().setEnabled(true); 165 WebCore::iconDatabase().open(WTF::String::fromUTF8(directory), WebCore::IconDatabase::defaultDatabaseFilename()); 166 if (!_ewk_icon_database_path) 167 _ewk_icon_database_path = eina_stringshare_add(directory); 168 else 169 eina_stringshare_replace(&_ewk_icon_database_path, directory); 170 } else { 171 WebCore::iconDatabase().setEnabled(false); 172 WebCore::iconDatabase().close(); 173 if (_ewk_icon_database_path) { 174 eina_stringshare_del(_ewk_icon_database_path); 175 _ewk_icon_database_path = 0; 176 } 177 } 178 return EINA_TRUE; 179 } 180 181 /** 182 * Returns directory path where icon database is stored. 183 * 184 * This is guaranteed to be eina_stringshare, so whenever possible 185 * save yourself some cpu cycles and use eina_stringshare_ref() 186 * instead of eina_stringshare_add() or strdup(). 187 * 188 * @return database path or @c 0 if none is set or database is closed 189 */ 190 const char* ewk_settings_icon_database_path_get(void) 191 { 192 if (!WebCore::iconDatabase().isEnabled()) 193 return 0; 194 if (!WebCore::iconDatabase().isOpen()) 195 return 0; 196 197 return _ewk_icon_database_path; 198 } 199 200 /** 201 * Removes all known icons from database. 202 * 203 * Database must be opened with ewk_settings_icon_database_path_set() 204 * in order to work. 205 * 206 * @return @c EINA_TRUE on success or @c EINA_FALSE otherwise, like 207 * closed database. 208 */ 209 Eina_Bool ewk_settings_icon_database_clear(void) 210 { 211 if (!WebCore::iconDatabase().isEnabled()) 212 return EINA_FALSE; 213 if (!WebCore::iconDatabase().isOpen()) 214 return EINA_FALSE; 215 216 WebCore::iconDatabase().removeAllIcons(); 217 return EINA_TRUE; 218 } 219 220 /** 221 * Queries icon for given URL, returning associated cairo surface. 222 * 223 * @note In order to have this working, one must open icon database 224 * with ewk_settings_icon_database_path_set(). 225 * 226 * @param url which url to query icon 227 * 228 * @return cairo surface if any, or @c 0 on failure 229 */ 230 cairo_surface_t* ewk_settings_icon_database_icon_surface_get(const char *url) 231 { 232 EINA_SAFETY_ON_NULL_RETURN_VAL(url, 0); 233 234 WebCore::KURL kurl(WebCore::KURL(), WTF::String::fromUTF8(url)); 235 WebCore::Image *icon = WebCore::iconDatabase().synchronousIconForPageURL(kurl.string(), WebCore::IntSize(16, 16)); 236 237 if (!icon) { 238 ERR("no icon for url %s", url); 239 return 0; 240 } 241 242 return icon->nativeImageForCurrentFrame(); 243 } 244 245 /** 246 * Creates Evas_Object of type image representing the given URL. 247 * 248 * This is an utility function that creates an Evas_Object of type 249 * image set to have fill always match object size 250 * (evas_object_image_filled_add()), saving some code to use it from Evas. 251 * 252 * @note In order to have this working, one must open icon database 253 * with ewk_settings_icon_database_path_set(). 254 * 255 * @param url which url to query icon 256 * @param canvas evas instance where to add resulting object 257 * 258 * @return newly allocated Evas_Object instance or @c 0 on 259 * errors. Delete the object with evas_object_del(). 260 */ 261 Evas_Object* ewk_settings_icon_database_icon_object_add(const char* url, Evas* canvas) 262 { 263 EINA_SAFETY_ON_NULL_RETURN_VAL(url, 0); 264 EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0); 265 266 WebCore::KURL kurl(WebCore::KURL(), WTF::String::fromUTF8(url)); 267 WebCore::Image* icon = WebCore::iconDatabase().synchronousIconForPageURL(kurl.string(), WebCore::IntSize(16, 16)); 268 cairo_surface_t* surface; 269 270 if (!icon) { 271 ERR("no icon for url %s", url); 272 return 0; 273 } 274 275 surface = icon->nativeImageForCurrentFrame(); 276 return ewk_util_image_from_cairo_surface_add(canvas, surface); 277 } 278 279 /** 280 * Sets the given proxy URI to network backend. 281 * 282 * @param proxy URI to set 283 */ 284 void ewk_settings_proxy_uri_set(const char* proxy) 285 { 286 #if USE(SOUP) 287 SoupSession* session = WebCore::ResourceHandle::defaultSession(); 288 289 if (!proxy) { 290 ERR("no proxy uri. remove proxy feature in soup."); 291 soup_session_remove_feature_by_type(session, SOUP_TYPE_PROXY_RESOLVER); 292 return; 293 } 294 295 SoupURI* uri = soup_uri_new(proxy); 296 EINA_SAFETY_ON_NULL_RETURN(uri); 297 298 g_object_set(session, SOUP_SESSION_PROXY_URI, uri, NULL); 299 soup_uri_free(uri); 300 #elif USE(CURL) 301 EINA_SAFETY_ON_TRUE_RETURN(1); 302 #endif 303 } 304 305 /** 306 * Gets the proxy URI from the network backend. 307 * 308 * @return current proxy URI or @c 0 if it's not set 309 */ 310 const char* ewk_settings_proxy_uri_get(void) 311 { 312 #if USE(SOUP) 313 SoupURI* uri; 314 SoupSession* session = WebCore::ResourceHandle::defaultSession(); 315 g_object_get(session, SOUP_SESSION_PROXY_URI, &uri, NULL); 316 317 if (!uri) { 318 ERR("no proxy uri"); 319 return 0; 320 } 321 322 WTF::String proxy = soup_uri_to_string(uri, EINA_FALSE); 323 return eina_stringshare_add(proxy.utf8().data()); 324 #elif USE(CURL) 325 EINA_SAFETY_ON_TRUE_RETURN_VAL(1, 0); 326 #endif 327 } 328 329 /** 330 * Gets status of the memory cache of WebCore. 331 * 332 * @return @c EINA_TRUE if the cache is enabled or @c EINA_FALSE if not 333 */ 334 Eina_Bool ewk_settings_cache_enable_get(void) 335 { 336 WebCore::MemoryCache* cache = WebCore::memoryCache(); 337 return !cache->disabled(); 338 } 339 340 /** 341 * Enables/disables the memory cache of WebCore, possibly clearing it. 342 * 343 * Disabling the cache will remove all resources from the cache. 344 * They may still live on if they are referenced by some Web page though. 345 * 346 * @param set @c EINA_TRUE to enable memory cache, @c EINA_FALSE to disable 347 */ 348 void ewk_settings_cache_enable_set(Eina_Bool set) 349 { 350 WebCore::MemoryCache* cache = WebCore::memoryCache(); 351 set = !set; 352 if (cache->disabled() != set) 353 cache->setDisabled(set); 354 } 355 356 /** 357 * Sets capacity of memory cache of WebCore. 358 * 359 * WebCore sets default value of memory cache on 8192 * 1024 bytes. 360 * 361 * @param capacity the maximum number of bytes that the cache should consume overall 362 */ 363 void ewk_settings_cache_capacity_set(unsigned capacity) 364 { 365 WebCore::MemoryCache* cache = WebCore::memoryCache(); 366 cache->setCapacities(0, capacity, capacity); 367 } 368 369 /** 370 * @internal 371 * 372 * Gets the default user agent string. 373 * 374 * @return a pointer to an eina_stringshare containing the user agent string 375 */ 376 const char* ewk_settings_default_user_agent_get(void) 377 { 378 WTF::String ua_version = makeString(String::number(WEBKIT_USER_AGENT_MAJOR_VERSION), '.', String::number(WEBKIT_USER_AGENT_MINOR_VERSION), '+'); 379 WTF::String static_ua = makeString("Mozilla/5.0 (", _ewk_settings_webkit_platform_get(), "; ", _ewk_settings_webkit_os_version_get(), ") AppleWebKit/", ua_version) + makeString(" (KHTML, like Gecko) Version/5.0 Safari/", ua_version); 380 381 return eina_stringshare_add(static_ua.utf8().data()); 382 } 383 384 /** 385 * Sets cache directory. 386 * 387 * @param path where to store cache, must be write-able. 388 * 389 * @return @c EINA_TRUE on success, @c EINA_FALSE if path is NULL or offline 390 * web application is not supported. 391 */ 392 Eina_Bool ewk_settings_cache_directory_path_set(const char *path) 393 { 394 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 395 if (!path) 396 return EINA_FALSE; 397 398 WebCore::cacheStorage().setCacheDirectory(WTF::String::fromUTF8(path)); 399 if (!_ewk_cache_directory_path) 400 _ewk_cache_directory_path = eina_stringshare_add(path); 401 else 402 eina_stringshare_replace(&_ewk_cache_directory_path, path); 403 return EINA_TRUE; 404 #else 405 EINA_SAFETY_ON_TRUE_RETURN_VAL(1, EINA_FALSE); 406 #endif 407 } 408 409 /** 410 * Return cache directory path. 411 * 412 * This is guaranteed to be eina_stringshare, so whenever possible 413 * save yourself some cpu cycles and use eina_stringshare_ref() 414 * instead of eina_stringshare_add() or strdup(). 415 * 416 * @return cache directory path. 417 */ 418 const char *ewk_settings_cache_directory_path_get() 419 { 420 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 421 return _ewk_cache_directory_path; 422 #else 423 EINA_SAFETY_ON_TRUE_RETURN_VAL(1, 0); 424 #endif 425 } 426