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 "FrameNetworkingContextGtk.h"
27#include "GOwnPtr.h"
28#include "IconDatabase.h"
29#include "Logging.h"
30#include "MemoryCache.h"
31#include "Page.h"
32#include "PageCache.h"
33#include "PageGroup.h"
34#include "TextEncodingRegistry.h"
35#include "Pasteboard.h"
36#include "PasteboardHelperGtk.h"
37#include "ResourceHandle.h"
38#include "ResourceHandleClient.h"
39#include "ResourceHandleInternal.h"
40#include "ResourceResponse.h"
41#include "webkitapplicationcache.h"
42#include "webkitglobalsprivate.h"
43#include "webkiticondatabase.h"
44#include "webkitsoupauthdialog.h"
45#include "webkitwebdatabase.h"
46#include "webkitwebplugindatabaseprivate.h"
47#include <libintl.h>
48#include <runtime/InitializeThreading.h>
49#include <stdlib.h>
50#include <wtf/Threading.h>
51
52static WebKitCacheModel cacheModel = WEBKIT_CACHE_MODEL_DEFAULT;
53
54using namespace WebCore;
55
56/**
57 * SECTION:webkit
58 * @short_description: Global functions controlling WebKit
59 *
60 * WebKit manages many resources which are not related to specific
61 * views. These functions relate to cross-view limits, such as cache
62 * sizes, database quotas, and the HTTP session management.
63 */
64
65/**
66 * webkit_get_default_session:
67 *
68 * Retrieves the default #SoupSession used by all web views.
69 * Note that the session features are added by WebKit on demand,
70 * so if you insert your own #SoupCookieJar before any network
71 * traffic occurs, WebKit will use it instead of the default.
72 *
73 * Return value: (transfer none): the default #SoupSession
74 *
75 * Since: 1.1.1
76 */
77SoupSession* webkit_get_default_session ()
78{
79    webkitInit();
80    return ResourceHandle::defaultSession();
81}
82
83/**
84 * webkit_set_cache_model:
85 * @cache_model: a #WebKitCacheModel
86 *
87 * Specifies a usage model for WebViews, which WebKit will use to
88 * determine its caching behavior. All web views follow the cache
89 * model. This cache model determines the RAM and disk space to use
90 * for caching previously viewed content .
91 *
92 * Research indicates that users tend to browse within clusters of
93 * documents that hold resources in common, and to revisit previously
94 * visited documents. WebKit and the frameworks below it include
95 * built-in caches that take advantage of these patterns,
96 * substantially improving document load speed in browsing
97 * situations. The WebKit cache model controls the behaviors of all of
98 * these caches, including various WebCore caches.
99 *
100 * Browsers can improve document load speed substantially by
101 * specifying WEBKIT_CACHE_MODEL_WEB_BROWSER. Applications without a
102 * browsing interface can reduce memory usage substantially by
103 * specifying WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER. Default value is
104 * WEBKIT_CACHE_MODEL_WEB_BROWSER.
105 *
106 * Since: 1.1.18
107 */
108void webkit_set_cache_model(WebKitCacheModel model)
109{
110    webkitInit();
111
112    if (cacheModel == model)
113        return;
114
115    // FIXME: Add disk cache handling when soup has the API
116    guint cacheTotalCapacity;
117    guint cacheMinDeadCapacity;
118    guint cacheMaxDeadCapacity;
119    gdouble deadDecodedDataDeletionInterval;
120    guint pageCacheCapacity;
121
122    // FIXME: The Mac port calculates these values based on the amount of physical memory that's
123    // installed on the system. Currently these values match the Mac port for users with more than
124    // 512 MB and less than 1024 MB of physical memory.
125    switch (model) {
126    case WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER:
127        pageCacheCapacity = 0;
128        cacheTotalCapacity = 0; // FIXME: The Mac port actually sets this to larger than 0.
129        cacheMinDeadCapacity = 0;
130        cacheMaxDeadCapacity = 0;
131        deadDecodedDataDeletionInterval = 0;
132        break;
133    case WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER:
134        pageCacheCapacity = 2;
135        cacheTotalCapacity = 16 * 1024 * 1024;
136        cacheMinDeadCapacity = cacheTotalCapacity / 8;
137        cacheMaxDeadCapacity = cacheTotalCapacity / 4;
138        deadDecodedDataDeletionInterval = 0;
139        break;
140    case WEBKIT_CACHE_MODEL_WEB_BROWSER:
141        // Page cache capacity (in pages). Comment from Mac port:
142        // (Research indicates that value / page drops substantially after 3 pages.)
143        pageCacheCapacity = 3;
144        cacheTotalCapacity = 32 * 1024 * 1024;
145        cacheMinDeadCapacity = cacheTotalCapacity / 4;
146        cacheMaxDeadCapacity = cacheTotalCapacity / 2;
147        deadDecodedDataDeletionInterval = 60;
148        break;
149    default:
150        g_return_if_reached();
151    }
152
153    memoryCache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
154    memoryCache()->setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
155    pageCache()->setCapacity(pageCacheCapacity);
156    cacheModel = model;
157}
158
159/**
160 * webkit_get_cache_model:
161 *
162 * Returns the current cache model. For more information about this
163 * value check the documentation of the function
164 * webkit_set_cache_model().
165 *
166 * Return value: the current #WebKitCacheModel
167 *
168 * Since: 1.1.18
169 */
170WebKitCacheModel webkit_get_cache_model()
171{
172    webkitInit();
173    return cacheModel;
174}
175
176/**
177 * webkit_get_web_plugin_database:
178 *
179 * Returns the current #WebKitWebPluginDatabase with information about
180 * all the plugins WebKit knows about in this instance.
181 *
182 * Return value: (transfer none): the current #WebKitWebPluginDatabase
183 *
184 * Since: 1.3.8
185 */
186WebKitWebPluginDatabase* webkit_get_web_plugin_database()
187{
188    static WebKitWebPluginDatabase* database = 0;
189
190    webkitInit();
191
192    if (!database)
193        database = webkit_web_plugin_database_new();
194
195    return database;
196}
197
198
199static GtkWidget* currentToplevelCallback(WebKitSoupAuthDialog* feature, SoupMessage* message, gpointer userData)
200{
201    gpointer messageData = g_object_get_data(G_OBJECT(message), "resourceHandle");
202    if (!messageData)
203        return NULL;
204
205    ResourceHandle* handle = static_cast<ResourceHandle*>(messageData);
206    if (!handle)
207        return NULL;
208
209    ResourceHandleInternal* d = handle->getInternal();
210    if (!d)
211        return NULL;
212
213    WebKit::FrameNetworkingContextGtk* context = static_cast<WebKit::FrameNetworkingContextGtk*>(d->m_context.get());
214    if (!context)
215        return NULL;
216
217    if (!context->coreFrame())
218        return NULL;
219
220    GtkWidget* toplevel =  gtk_widget_get_toplevel(GTK_WIDGET(context->coreFrame()->page()->chrome()->platformPageClient()));
221    if (gtk_widget_is_toplevel(toplevel))
222        return toplevel;
223    else
224        return NULL;
225}
226
227/**
228 * webkit_get_icon_database:
229 *
230 * Returns the #WebKitIconDatabase providing access to website icons.
231 *
232 * Return value: (transfer none): the current #WebKitIconDatabase
233 *
234 * Since: 1.3.13
235 */
236WebKitIconDatabase* webkit_get_icon_database()
237{
238    webkitInit();
239
240    static WebKitIconDatabase* database = 0;
241    if (!database)
242        database = WEBKIT_ICON_DATABASE(g_object_new(WEBKIT_TYPE_ICON_DATABASE, NULL));
243
244    return database;
245}
246
247void webkitInit()
248{
249    static bool isInitialized = false;
250    if (isInitialized)
251        return;
252    isInitialized = true;
253
254    bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
255    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
256
257    JSC::initializeThreading();
258    WTF::initializeMainThread();
259
260    WebCore::InitializeLoggingChannelsIfNecessary();
261
262    // We make sure the text codecs have been initialized, because
263    // that may only be done by the main thread.
264    atomicCanonicalTextEncodingName("UTF-8");
265
266    gchar* databaseDirectory = g_build_filename(g_get_user_data_dir(), "webkit", "databases", NULL);
267    webkit_set_web_database_directory_path(databaseDirectory);
268    WebCore::cacheStorage().setCacheDirectory(databaseDirectory);
269
270    g_free(databaseDirectory);
271
272    PageGroup::setShouldTrackVisitedLinks(true);
273
274    Pasteboard::generalPasteboard()->setHelper(WebKit::pasteboardHelperInstance());
275    GOwnPtr<gchar> iconDatabasePath(g_build_filename(g_get_user_data_dir(), "webkit", "icondatabase", NULL));
276    webkit_icon_database_set_path(webkit_get_icon_database(), iconDatabasePath.get());
277
278    SoupSession* session = webkit_get_default_session();
279
280    SoupSessionFeature* authDialog = static_cast<SoupSessionFeature*>(g_object_new(WEBKIT_TYPE_SOUP_AUTH_DIALOG, NULL));
281    g_signal_connect(authDialog, "current-toplevel", G_CALLBACK(currentToplevelCallback), NULL);
282    soup_session_add_feature(session, authDialog);
283    g_object_unref(authDialog);
284
285    SoupSessionFeature* sniffer = static_cast<SoupSessionFeature*>(g_object_new(SOUP_TYPE_CONTENT_SNIFFER, NULL));
286    soup_session_add_feature(session, sniffer);
287    g_object_unref(sniffer);
288
289    soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER);
290}
291
292namespace WebKit {
293
294PasteboardHelperGtk* pasteboardHelperInstance()
295{
296    static PasteboardHelperGtk* helper = new PasteboardHelperGtk();
297    return helper;
298}
299
300} /** end namespace WebKit */
301
302