Home | History | Annotate | Download | only in ewk
      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