1 /* 2 * Copyright (C) 2011 Christian Dywan <christian (at) lanedo.com> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #include "config.h" 21 #include "webkiticondatabase.h" 22 23 #include "DatabaseDetails.h" 24 #include "DatabaseTracker.h" 25 #include "FileSystem.h" 26 #include "IconDatabase.h" 27 #include "Image.h" 28 #include "IntSize.h" 29 #include "webkitglobalsprivate.h" 30 #include "webkitmarshal.h" 31 #include "webkitsecurityoriginprivate.h" 32 #include "webkitwebframe.h" 33 #include <glib/gi18n-lib.h> 34 #include <wtf/gobject/GOwnPtr.h> 35 #include <wtf/text/CString.h> 36 37 /** 38 * SECTION:webkitwebdatabase 39 * @short_description: A WebKit web application database 40 * 41 * #WebKitIconDatabase provides access to website icons, as shown 42 * in tab labels, window captions or bookmarks. All views share 43 * the same icon database. 44 * 45 * The icon database is enabled by default and stored in 46 * ~/.local/share/webkit/icondatabase, depending on XDG_DATA_HOME. 47 * 48 * WebKit will automatically look for available icons in link elements 49 * on opened pages as well as an existing favicon.ico and load the 50 * images found into the memory cache if possible. The signal "icon-loaded" 51 * will be emitted when any icon is found and loaded. 52 * Old Icons are automatically cleaned up after 4 days. 53 * 54 * webkit_icon_database_set_path() can be used to change the location 55 * of the database and also to disable it by passing %NULL. 56 * 57 * If WebKitWebSettings::enable-private-browsing is %TRUE new icons 58 * won't be added to the database on disk and no existing icons will 59 * be deleted from it. 60 * 61 * Since: 1.3.13 62 */ 63 64 using namespace WebKit; 65 66 enum { 67 PROP_0, 68 69 PROP_PATH, 70 }; 71 72 enum { 73 ICON_LOADED, 74 75 LAST_SIGNAL 76 }; 77 78 static guint webkit_icon_database_signals[LAST_SIGNAL] = { 0, }; 79 80 G_DEFINE_TYPE(WebKitIconDatabase, webkit_icon_database, G_TYPE_OBJECT); 81 82 struct _WebKitIconDatabasePrivate { 83 GOwnPtr<gchar> path; 84 }; 85 86 static void webkit_icon_database_finalize(GObject* object) 87 { 88 // Call C++ destructors, the reverse of 'placement new syntax' 89 WEBKIT_ICON_DATABASE(object)->priv->~WebKitIconDatabasePrivate(); 90 91 G_OBJECT_CLASS(webkit_icon_database_parent_class)->finalize(object); 92 } 93 94 static void webkit_icon_database_dispose(GObject* object) 95 { 96 G_OBJECT_CLASS(webkit_icon_database_parent_class)->dispose(object); 97 } 98 99 static void webkit_icon_database_set_property(GObject* object, guint propId, const GValue* value, GParamSpec* pspec) 100 { 101 WebKitIconDatabase* database = WEBKIT_ICON_DATABASE(object); 102 103 switch (propId) { 104 case PROP_PATH: 105 webkit_icon_database_set_path(database, g_value_get_string(value)); 106 break; 107 default: 108 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); 109 break; 110 } 111 } 112 113 static void webkit_icon_database_get_property(GObject* object, guint propId, GValue* value, GParamSpec* pspec) 114 { 115 WebKitIconDatabase* database = WEBKIT_ICON_DATABASE(object); 116 117 switch (propId) { 118 case PROP_PATH: 119 g_value_set_string(value, webkit_icon_database_get_path(database)); 120 break; 121 default: 122 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); 123 break; 124 } 125 } 126 127 static void webkit_icon_database_class_init(WebKitIconDatabaseClass* klass) 128 { 129 webkitInit(); 130 131 GObjectClass* gobjectClass = G_OBJECT_CLASS(klass); 132 gobjectClass->dispose = webkit_icon_database_dispose; 133 gobjectClass->finalize = webkit_icon_database_finalize; 134 gobjectClass->set_property = webkit_icon_database_set_property; 135 gobjectClass->get_property = webkit_icon_database_get_property; 136 137 /** 138 * WebKitIconDatabase:path: 139 * 140 * The absolute path of the icon database folder. 141 * 142 * Since: 1.3.13 143 */ 144 g_object_class_install_property(gobjectClass, PROP_PATH, 145 g_param_spec_string("path", 146 _("Path"), 147 _("The absolute path of the icon database folder"), 148 NULL, 149 WEBKIT_PARAM_READWRITE)); 150 151 /** 152 * WebKitIconDatabase::icon-loaded: 153 * @database: the object on which the signal is emitted 154 * @frame: the frame containing the icon 155 * @frame_uri: the URI of the frame containing the icon 156 * 157 * This signal is emitted when a favicon is available for a page, 158 * or a child frame. 159 * See WebKitWebView::icon-loaded if you only need the favicon for 160 * the main frame of a particular #WebKitWebView. 161 * 162 * Since: 1.3.13 163 */ 164 webkit_icon_database_signals[ICON_LOADED] = g_signal_new("icon-loaded", 165 G_TYPE_FROM_CLASS(klass), 166 (GSignalFlags)G_SIGNAL_RUN_LAST, 167 0, 168 NULL, 169 NULL, 170 webkit_marshal_VOID__OBJECT_STRING, 171 G_TYPE_NONE, 2, 172 WEBKIT_TYPE_WEB_FRAME, 173 G_TYPE_STRING); 174 175 g_type_class_add_private(klass, sizeof(WebKitIconDatabasePrivate)); 176 } 177 178 static void webkit_icon_database_init(WebKitIconDatabase* database) 179 { 180 database->priv = G_TYPE_INSTANCE_GET_PRIVATE(database, WEBKIT_TYPE_ICON_DATABASE, WebKitIconDatabasePrivate); 181 // 'placement new syntax', see webkitwebview.cpp 182 new (database->priv) WebKitIconDatabasePrivate(); 183 } 184 185 /** 186 * webkit_icon_database_get_path: 187 * @database: a #WebKitIconDatabase 188 * 189 * Determines the absolute path to the database folder on disk. 190 * 191 * Returns: the absolute path of the database folder, or %NULL 192 * 193 * Since: 1.3.13 194 **/ 195 G_CONST_RETURN gchar* webkit_icon_database_get_path(WebKitIconDatabase* database) 196 { 197 g_return_val_if_fail(WEBKIT_IS_ICON_DATABASE(database), 0); 198 199 return database->priv->path.get(); 200 } 201 202 static void closeIconDatabaseOnExit() 203 { 204 if (WebCore::iconDatabase().isEnabled()) { 205 WebCore::iconDatabase().setEnabled(false); 206 WebCore::iconDatabase().close(); 207 } 208 } 209 210 /** 211 * webkit_icon_database_set_path: 212 * @database: a #WebKitIconDatabase 213 * @path: an absolute path to the icon database folder 214 * 215 * Specifies the absolute path to the database folder on disk. 216 * 217 * Passing %NULL or "" disables the icon database. 218 * 219 * Since: 1.3.13 220 **/ 221 void webkit_icon_database_set_path(WebKitIconDatabase* database, const gchar* path) 222 { 223 g_return_if_fail(WEBKIT_IS_ICON_DATABASE(database)); 224 225 if (database->priv->path.get()) 226 WebCore::iconDatabase().close(); 227 228 if (!(path && path[0])) { 229 database->priv->path.set(0); 230 WebCore::iconDatabase().setEnabled(false); 231 return; 232 } 233 234 database->priv->path.set(g_strdup(path)); 235 236 WebCore::iconDatabase().setEnabled(true); 237 WebCore::iconDatabase().open(WebCore::filenameToString(database->priv->path.get()), WebCore::IconDatabase::defaultDatabaseFilename()); 238 239 static bool initialized = false; 240 if (!initialized) { 241 atexit(closeIconDatabaseOnExit); 242 initialized = true; 243 } 244 } 245 246 /** 247 * webkit_icon_database_get_icon_uri: 248 * @database: a #WebKitIconDatabase 249 * @page_uri: URI of the page containing the icon 250 * 251 * Obtains the URI for the favicon for the given page URI. 252 * See also webkit_web_view_get_icon_uri(). 253 * 254 * Returns: a newly allocated URI for the favicon, or %NULL 255 * 256 * Since: 1.3.13 257 **/ 258 gchar* webkit_icon_database_get_icon_uri(WebKitIconDatabase* database, const gchar* pageURI) 259 { 260 g_return_val_if_fail(WEBKIT_IS_ICON_DATABASE(database), 0); 261 g_return_val_if_fail(pageURI, 0); 262 263 String pageURL = String::fromUTF8(pageURI); 264 return g_strdup(WebCore::iconDatabase().synchronousIconURLForPageURL(pageURL).utf8().data()); 265 } 266 267 /** 268 * webkit_icon_database_get_icon_pixbuf: 269 * @database: a #WebKitIconDatabase 270 * @page_uri: URI of the page containing the icon 271 * 272 * Obtains a #GdkPixbuf of the favicon for the given page URI, or 273 * a default icon if there is no icon for the given page. Use 274 * webkit_icon_database_get_icon_uri() if you need to distinguish these cases. 275 * Usually you want to connect to WebKitIconDatabase::icon-loaded and call this 276 * method in the callback. 277 * 278 * The pixbuf will have the largest size provided by the server and should 279 * be resized before it is displayed. 280 * See also webkit_web_view_get_icon_pixbuf(). 281 * 282 * Returns: (transfer full): a new reference to a #GdkPixbuf, or %NULL 283 * 284 * Since: 1.3.13 285 **/ 286 GdkPixbuf* webkit_icon_database_get_icon_pixbuf(WebKitIconDatabase* database, const gchar* pageURI) 287 { 288 g_return_val_if_fail(WEBKIT_IS_ICON_DATABASE(database), 0); 289 g_return_val_if_fail(pageURI, 0); 290 291 String pageURL = String::fromUTF8(pageURI); 292 // The exact size we pass is irrelevant to the WebCore::iconDatabase code. 293 // We must pass something greater than 0, 0 to get a pixbuf. 294 WebCore::Image* icon = WebCore::iconDatabase().synchronousIconForPageURL(pageURL, WebCore::IntSize(16, 16)); 295 if (!icon) 296 return 0; 297 GdkPixbuf* pixbuf = icon->getGdkPixbuf(); 298 if (!pixbuf) 299 return 0; 300 return static_cast<GdkPixbuf*>(g_object_ref(pixbuf)); 301 } 302 303 /** 304 * webkit_icon_database_clear(): 305 * @database: a #WebKitIconDatabase 306 * 307 * Clears all icons from the database. 308 * 309 * Since: 1.3.13 310 **/ 311 void webkit_icon_database_clear(WebKitIconDatabase* database) 312 { 313 g_return_if_fail(WEBKIT_IS_ICON_DATABASE(database)); 314 315 WebCore::iconDatabase().removeAllIcons(); 316 } 317 318