1/*
2 * Copyright (C) 2007 Holger Hans Peter Freyther
3 * Copyright (C) 2008, 2010 Collabora Ltd.
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 "webkitglobals.h"
23
24#include "ApplicationCacheStorage.h"
25#include "Chrome.h"
26#include "ContextMenuItem.h"
27#include "FrameNetworkingContextGtk.h"
28#include "IconDatabase.h"
29#include "InitializeLogging.h"
30#include "MemoryCache.h"
31#include "Page.h"
32#include "PageCache.h"
33#include "PageGroup.h"
34#include "PlatformStrategiesGtk.h"
35#include "TextEncodingRegistry.h"
36#include "Pasteboard.h"
37#include "PasteboardHelperGtk.h"
38#include "ResourceHandle.h"
39#include "ResourceHandleClient.h"
40#include "ResourceHandleInternal.h"
41#include "ResourceResponse.h"
42#include "SchemeRegistry.h"
43#include "webkitapplicationcache.h"
44#include "webkitfavicondatabase.h"
45#include "webkitglobalsprivate.h"
46#include "webkiticondatabase.h"
47#include "webkitspellchecker.h"
48#include "webkitspellcheckerenchant.h"
49#include "webkitwebdatabase.h"
50#include "webkitwebplugindatabaseprivate.h"
51#include <libintl.h>
52#include <runtime/InitializeThreading.h>
53#include <stdlib.h>
54#include <wtf/MainThread.h>
55#include <wtf/gobject/GOwnPtr.h>
56#include <wtf/gobject/GRefPtr.h>
57
58#if USE(CLUTTER)
59#include <clutter-gtk/clutter-gtk.h>
60#endif
61
62static WebKitCacheModel cacheModel = WEBKIT_CACHE_MODEL_DEFAULT;
63
64using namespace WebCore;
65
66/**
67 * SECTION:webkit
68 * @short_description: Global functions controlling WebKit
69 *
70 * WebKit manages many resources which are not related to specific
71 * views. These functions relate to cross-view limits, such as cache
72 * sizes, database quotas, and the HTTP session management.
73 */
74
75/**
76 * webkit_get_default_session:
77 *
78 * Retrieves the default #SoupSession used by all web views.
79 * Note that the session features are added by WebKit on demand,
80 * so if you insert your own #SoupCookieJar before any network
81 * traffic occurs, WebKit will use it instead of the default.
82 *
83 * Return value: (transfer none): the default #SoupSession
84 *
85 * Since: 1.1.1
86 */
87SoupSession* webkit_get_default_session ()
88{
89    webkitInit();
90    return ResourceHandle::defaultSession();
91}
92
93/**
94 * webkit_set_cache_model:
95 * @cache_model: a #WebKitCacheModel
96 *
97 * Specifies a usage model for WebViews, which WebKit will use to
98 * determine its caching behavior. All web views follow the cache
99 * model. This cache model determines the RAM and disk space to use
100 * for caching previously viewed content .
101 *
102 * Research indicates that users tend to browse within clusters of
103 * documents that hold resources in common, and to revisit previously
104 * visited documents. WebKit and the frameworks below it include
105 * built-in caches that take advantage of these patterns,
106 * substantially improving document load speed in browsing
107 * situations. The WebKit cache model controls the behaviors of all of
108 * these caches, including various WebCore caches.
109 *
110 * Browsers can improve document load speed substantially by
111 * specifying WEBKIT_CACHE_MODEL_WEB_BROWSER. Applications without a
112 * browsing interface can reduce memory usage substantially by
113 * specifying WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER. Default value is
114 * WEBKIT_CACHE_MODEL_WEB_BROWSER.
115 *
116 * Since: 1.1.18
117 */
118void webkit_set_cache_model(WebKitCacheModel model)
119{
120    webkitInit();
121
122    if (cacheModel == model)
123        return;
124
125    // FIXME: Add disk cache handling when soup has the API
126    guint cacheTotalCapacity;
127    guint cacheMinDeadCapacity;
128    guint cacheMaxDeadCapacity;
129    gdouble deadDecodedDataDeletionInterval;
130    guint pageCacheCapacity;
131
132    // FIXME: The Mac port calculates these values based on the amount of physical memory that's
133    // installed on the system. Currently these values match the Mac port for users with more than
134    // 512 MB and less than 1024 MB of physical memory.
135    switch (model) {
136    case WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER:
137        pageCacheCapacity = 0;
138        cacheTotalCapacity = 0; // FIXME: The Mac port actually sets this to larger than 0.
139        cacheMinDeadCapacity = 0;
140        cacheMaxDeadCapacity = 0;
141        deadDecodedDataDeletionInterval = 0;
142        break;
143    case WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER:
144        pageCacheCapacity = 2;
145        cacheTotalCapacity = 16 * 1024 * 1024;
146        cacheMinDeadCapacity = cacheTotalCapacity / 8;
147        cacheMaxDeadCapacity = cacheTotalCapacity / 4;
148        deadDecodedDataDeletionInterval = 0;
149        break;
150    case WEBKIT_CACHE_MODEL_WEB_BROWSER:
151        // Page cache capacity (in pages). Comment from Mac port:
152        // (Research indicates that value / page drops substantially after 3 pages.)
153        pageCacheCapacity = 3;
154        cacheTotalCapacity = 32 * 1024 * 1024;
155        cacheMinDeadCapacity = cacheTotalCapacity / 4;
156        cacheMaxDeadCapacity = cacheTotalCapacity / 2;
157        deadDecodedDataDeletionInterval = 60;
158        break;
159    default:
160        g_return_if_reached();
161    }
162
163    memoryCache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
164    memoryCache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
165    pageCache()->setCapacity(pageCacheCapacity);
166    cacheModel = model;
167}
168
169/**
170 * webkit_get_cache_model:
171 *
172 * Returns the current cache model. For more information about this
173 * value check the documentation of the function
174 * webkit_set_cache_model().
175 *
176 * Return value: the current #WebKitCacheModel
177 *
178 * Since: 1.1.18
179 */
180WebKitCacheModel webkit_get_cache_model()
181{
182    webkitInit();
183    return cacheModel;
184}
185
186/**
187 * webkit_get_web_plugin_database:
188 *
189 * Returns the current #WebKitWebPluginDatabase with information about
190 * all the plugins WebKit knows about in this instance.
191 *
192 * Return value: (transfer none): the current #WebKitWebPluginDatabase
193 *
194 * Since: 1.3.8
195 */
196WebKitWebPluginDatabase* webkit_get_web_plugin_database()
197{
198    static WebKitWebPluginDatabase* database = 0;
199
200    webkitInit();
201
202    if (!database)
203        database = webkit_web_plugin_database_new();
204
205    return database;
206}
207
208/**
209 * webkit_get_icon_database:
210 *
211 * Returns the #WebKitIconDatabase providing access to website icons.
212 *
213 * Return value: (transfer none): the current #WebKitIconDatabase
214 *
215 * Since: 1.3.13
216 *
217 * Deprecated: 1.8: Use webkit_get_favicon_database() instead
218 */
219WebKitIconDatabase* webkit_get_icon_database()
220{
221    webkitInit();
222
223    static WebKitIconDatabase* database = 0;
224    if (!database)
225        database = WEBKIT_ICON_DATABASE(g_object_new(WEBKIT_TYPE_ICON_DATABASE, NULL));
226
227    return database;
228}
229
230/**
231 * webkit_get_favicon_database:
232 *
233 * Returns the #WebKitFaviconDatabase providing access to website
234 * icons.
235 *
236 * Return value: (transfer none): the current #WebKitFaviconDatabase
237 *
238 * Since: 1.8
239 */
240WebKitFaviconDatabase* webkit_get_favicon_database()
241{
242    webkitInit();
243
244    static WebKitFaviconDatabase* database = 0;
245    if (!database)
246        database = WEBKIT_FAVICON_DATABASE(g_object_new(WEBKIT_TYPE_FAVICON_DATABASE, NULL));
247
248    return database;
249}
250
251static GRefPtr<WebKitSpellChecker> textChecker = 0;
252
253static void webkitExit()
254{
255    g_object_unref(webkit_get_default_session());
256#if ENABLE(ICONDATABASE)
257    g_object_unref(webkit_get_favicon_database());
258#endif
259    textChecker = 0;
260}
261
262/**
263 * webkit_get_text_checker:
264 *
265 * Returns: (transfer none): the #WebKitSpellChecker used by WebKit, or %NULL if spell
266 * checking is not enabled
267 *
268 * Since: 1.5.1
269 **/
270GObject* webkit_get_text_checker()
271{
272    webkitInit();
273
274#if ENABLE(SPELLCHECK)
275    if (!textChecker)
276        textChecker = adoptGRef(WEBKIT_SPELL_CHECKER(g_object_new(WEBKIT_TYPE_SPELL_CHECKER_ENCHANT, NULL)));
277#endif
278
279    return G_OBJECT(textChecker.get());
280}
281
282/**
283 * webkit_set_text_checker:
284 * @checker: a #WebKitSpellChecker or %NULL
285 *
286 * Sets @checker as the spell checker to be used by WebKit. The API
287 * accepts GObject since in the future we might accept objects
288 * implementing multiple interfaces (for example, spell checking and
289 * grammar checking).
290 *
291 * Since: 1.5.1
292 **/
293void webkit_set_text_checker(GObject* checker)
294{
295    g_return_if_fail(!checker || WEBKIT_IS_SPELL_CHECKER(checker));
296
297    webkitInit();
298
299    // We need to do this because we need the cast, and casting NULL
300    // is not kosher.
301    textChecker = checker ? WEBKIT_SPELL_CHECKER(checker) : 0;
302}
303
304/**
305 * webkit_context_menu_item_get_action:
306 * @item: a #GtkMenuItem of the default context menu
307 *
308 * Returns the #WebKitContextMenuAction of the given @item. This function
309 * can be used to determine the items present in the default context menu.
310 * In order to inspect the default context menu, you should connect to
311 * #WebKitWebView::context-menu signal.
312 *
313 * <example>
314 * <title>Inspecting the default context menu</title>
315 * <programlisting>
316 * static gboolean context_menu_cb (WebKitWebView       *webView,
317 *                                  GtkWidget           *default_menu,
318 *                                  WebKitHitTestResult *hit_test_result,
319 *                                  gboolean             triggered_with_keyboard,
320 *                                  gpointer             user_data)
321 * {
322 *     GList *items = gtk_container_get_children (GTK_CONTAINER (default_menu));
323 *     GList *l;
324 *     GtkAction *action;
325 *     GtkWidget *sub_menu;
326 *
327 *     for (l = items; l; l = g_list_next (l)) {
328 *         GtkMenuItem *item = (GtkMenuItem *)l->data;
329 *
330 *         if (GTK_IS_SEPARATOR_MENU_ITEM (item)) {
331 *             /&ast; It's  separator, do nothing &ast;/
332 *             continue;
333 *         }
334 *
335 *         switch (webkit_context_menu_item_get_action (item)) {
336 *         case WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION:
337 *             /&ast; No action for this item &ast;/
338 *             break;
339 *         /&ast; Don't allow to ope links from context menu &ast;/
340 *         case WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK:
341 *         case WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW:
342 *             action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (item));
343 *             gtk_action_set_sensitive (action, FALSE);
344 *             break;
345 *         default:
346 *             break;
347 *         }
348 *
349 *         sub_menu = gtk_menu_item_get_submenu (item);
350 *         if (sub_menu) {
351 *             GtkWidget *menu_item;
352 *
353 *             /&ast; Add custom action to submenu &ast;/
354 *             action = gtk_action_new ("CustomItemName", "Custom Action", NULL, NULL);
355 *             g_signal_connect (action, "activate", G_CALLBACK (custom_menu_item_activated), NULL);
356 *
357 *             menu_item = gtk_action_create_menu_item (action);
358 *             g_object_unref (action);
359 *             gtk_menu_shell_append (GTK_MENU_SHELL (sub_menu), menu_item);
360 *             gtk_widget_show (menu_item);
361 *         }
362 *     }
363 *
364 *     g_list_free(items);
365 * }
366 * </programlisting>
367 * </example>
368 *
369 * Note that you can get the #GtkAction of any item in the default context menu with
370 * gtk_activatable_get_related_action().
371 *
372 * Returns: the #WebKitContextMenuAction of the given @item
373 *
374 * Since: 1.10
375 */
376WebKitContextMenuAction webkit_context_menu_item_get_action(GtkMenuItem* item)
377{
378#if ENABLE(CONTEXT_MENUS)
379    g_return_val_if_fail(GTK_IS_MENU_ITEM(item), WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION);
380
381    ContextMenuItem menuItem(item);
382    switch (menuItem.action()) {
383    case ContextMenuItemTagNoAction:
384        return WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION;
385    case ContextMenuItemTagOpenLink:
386        return WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK;
387    case ContextMenuItemTagOpenLinkInNewWindow:
388        return WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW;
389    case ContextMenuItemTagDownloadLinkToDisk:
390        return WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK;
391    case ContextMenuItemTagCopyLinkToClipboard:
392        return WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD;
393    case ContextMenuItemTagOpenImageInNewWindow:
394        return WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW;
395    case ContextMenuItemTagDownloadImageToDisk:
396        return WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK;
397    case ContextMenuItemTagCopyImageToClipboard:
398        return WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD;
399    case ContextMenuItemTagCopyImageUrlToClipboard:
400        return WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD;
401    case ContextMenuItemTagOpenFrameInNewWindow:
402        return WEBKIT_CONTEXT_MENU_ACTION_OPEN_FRAME_IN_NEW_WINDOW;
403    case ContextMenuItemTagGoBack:
404        return WEBKIT_CONTEXT_MENU_ACTION_GO_BACK;
405    case ContextMenuItemTagGoForward:
406        return WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD;
407    case ContextMenuItemTagStop:
408        return WEBKIT_CONTEXT_MENU_ACTION_STOP;
409    case ContextMenuItemTagReload:
410        return WEBKIT_CONTEXT_MENU_ACTION_RELOAD;
411    case ContextMenuItemTagCopy:
412        return WEBKIT_CONTEXT_MENU_ACTION_COPY;
413    case ContextMenuItemTagCut:
414        return WEBKIT_CONTEXT_MENU_ACTION_CUT;
415    case ContextMenuItemTagPaste:
416        return WEBKIT_CONTEXT_MENU_ACTION_PASTE;
417    case ContextMenuItemTagDelete:
418        return WEBKIT_CONTEXT_MENU_ACTION_DELETE;
419    case ContextMenuItemTagSelectAll:
420        return WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL;
421    case ContextMenuItemTagInputMethods:
422        return WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS;
423    case ContextMenuItemTagUnicode:
424        return WEBKIT_CONTEXT_MENU_ACTION_UNICODE;
425    case ContextMenuItemTagSpellingGuess:
426        return WEBKIT_CONTEXT_MENU_ACTION_SPELLING_GUESS;
427    case ContextMenuItemTagIgnoreSpelling:
428        return WEBKIT_CONTEXT_MENU_ACTION_IGNORE_SPELLING;
429    case ContextMenuItemTagLearnSpelling:
430        return WEBKIT_CONTEXT_MENU_ACTION_LEARN_SPELLING;
431    case ContextMenuItemTagIgnoreGrammar:
432        return WEBKIT_CONTEXT_MENU_ACTION_IGNORE_GRAMMAR;
433    case ContextMenuItemTagFontMenu:
434        return WEBKIT_CONTEXT_MENU_ACTION_FONT_MENU;
435    case ContextMenuItemTagBold:
436        return WEBKIT_CONTEXT_MENU_ACTION_BOLD;
437    case ContextMenuItemTagItalic:
438        return WEBKIT_CONTEXT_MENU_ACTION_ITALIC;
439    case ContextMenuItemTagUnderline:
440        return WEBKIT_CONTEXT_MENU_ACTION_UNDERLINE;
441    case ContextMenuItemTagOutline:
442        return WEBKIT_CONTEXT_MENU_ACTION_OUTLINE;
443    case ContextMenuItemTagInspectElement:
444        return WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT;
445    case ContextMenuItemTagOpenMediaInNewWindow:
446        return WEBKIT_CONTEXT_MENU_ACTION_OPEN_MEDIA_IN_NEW_WINDOW;
447    case ContextMenuItemTagCopyMediaLinkToClipboard:
448        return WEBKIT_CONTEXT_MENU_ACTION_COPY_MEDIA_LINK_TO_CLIPBOARD;
449    case ContextMenuItemTagToggleMediaControls:
450        return WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS;
451    case ContextMenuItemTagToggleMediaLoop:
452        return WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP;
453    case ContextMenuItemTagEnterVideoFullscreen:
454        return WEBKIT_CONTEXT_MENU_ACTION_ENTER_VIDEO_FULLSCREEN;
455    case ContextMenuItemTagMediaPlayPause:
456        return WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY_PAUSE;
457    case ContextMenuItemTagMediaMute:
458        return WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE;
459    default:
460        g_assert_not_reached();
461    }
462#else
463    return WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION;
464#endif
465}
466
467/**
468 * webkit_set_security_policy_for_uri_scheme:
469 * @scheme: a URI scheme
470 * @policy: a #WebKitSecurityPolicy
471 *
472 * Set the security policy for the given URI scheme.
473 *
474 * Since: 2.0
475 */
476void webkit_set_security_policy_for_uri_scheme(const char *scheme, WebKitSecurityPolicy policy)
477{
478    g_return_if_fail(scheme);
479
480    if (!policy)
481        return;
482
483    String urlScheme = String::fromUTF8(scheme);
484
485    if (policy & WEBKIT_SECURITY_POLICY_LOCAL)
486        SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
487    if (policy & WEBKIT_SECURITY_POLICY_NO_ACCESS_TO_OTHER_SCHEME)
488        SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
489    if (policy & WEBKIT_SECURITY_POLICY_DISPLAY_ISOLATED)
490        SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
491    if (policy & WEBKIT_SECURITY_POLICY_SECURE)
492        SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
493    if (policy & WEBKIT_SECURITY_POLICY_CORS_ENABLED)
494        SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
495    if (policy & WEBKIT_SECURITY_POLICY_EMPTY_DOCUMENT)
496        SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
497}
498
499/**
500 * webkit_get_security_policy_for_uri_scheme:
501 * @scheme: a URI scheme
502 *
503 * Get the security policy for the given URI scheme.
504 *
505 * Returns: a #WebKitSecurityPolicy
506 *
507 * Since: 2.0
508 */
509WebKitSecurityPolicy webkit_get_security_policy_for_uri_scheme(const char *scheme)
510{
511    g_return_val_if_fail(scheme, static_cast<WebKitSecurityPolicy>(0));
512
513    guint policy = 0;
514    String urlScheme = String::fromUTF8(scheme);
515
516    if (SchemeRegistry::shouldTreatURLSchemeAsLocal(urlScheme))
517        policy |= WEBKIT_SECURITY_POLICY_LOCAL;
518    if (SchemeRegistry::shouldTreatURLSchemeAsNoAccess(urlScheme))
519        policy |= WEBKIT_SECURITY_POLICY_NO_ACCESS_TO_OTHER_SCHEME;
520    if (SchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(urlScheme))
521        policy |= WEBKIT_SECURITY_POLICY_DISPLAY_ISOLATED;
522    if (SchemeRegistry::shouldTreatURLSchemeAsSecure(urlScheme))
523        policy |= WEBKIT_SECURITY_POLICY_SECURE;
524    if (SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(urlScheme))
525        policy |= WEBKIT_SECURITY_POLICY_CORS_ENABLED;
526    if (SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(urlScheme))
527        policy |= WEBKIT_SECURITY_POLICY_EMPTY_DOCUMENT;
528
529    return static_cast<WebKitSecurityPolicy>(policy);
530}
531
532void webkitInit()
533{
534    static bool isInitialized = false;
535    if (isInitialized)
536        return;
537    isInitialized = true;
538
539    bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
540    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
541
542    JSC::initializeThreading();
543    WTF::initializeMainThread();
544
545#if !LOG_DISABLED
546    WebCore::initializeLoggingChannelsIfNecessary();
547#endif // !LOG_DISABLED
548    PlatformStrategiesGtk::initialize();
549
550    // We make sure the text codecs have been initialized, because
551    // that may only be done by the main thread.
552    atomicCanonicalTextEncodingName("UTF-8");
553
554    GOwnPtr<gchar> databaseDirectory(g_build_filename(g_get_user_data_dir(), "webkit", "databases", NULL));
555    webkit_set_web_database_directory_path(databaseDirectory.get());
556
557    GOwnPtr<gchar> cacheDirectory(g_build_filename(g_get_user_cache_dir(), "webkitgtk", "applications", NULL));
558    WebCore::cacheStorage().setCacheDirectory(cacheDirectory.get());
559
560    PageGroup::setShouldTrackVisitedLinks(true);
561
562    GOwnPtr<gchar> iconDatabasePath(g_build_filename(g_get_user_data_dir(), "webkit", "icondatabase", NULL));
563    webkit_icon_database_set_path(webkit_get_icon_database(), iconDatabasePath.get());
564
565    WebCore::ResourceHandle::setIgnoreSSLErrors(true);
566
567#if USE(CLUTTER)
568    gtk_clutter_init(0, 0);
569#endif
570
571    atexit(webkitExit);
572}
573
574const char* webkitPageGroupName()
575{
576    return "org.webkit.gtk.WebKitGTK";
577}
578