1 /* 2 * Copyright (C) 2008, 2009 Jan Michael C. Alonzo 3 * Copyright (C) 2009 Igalia S.L. 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 23 #include "webkitwebhistoryitem.h" 24 #include "webkitprivate.h" 25 26 #include <glib.h> 27 #include <glib/gi18n-lib.h> 28 29 #include "CString.h" 30 #include "HistoryItem.h" 31 #include "PlatformString.h" 32 33 /** 34 * SECTION:webkitwebhistoryitem 35 * @short_description: One item of the #WebKitWebBackForwardList and or global history 36 * @see_also: #WebKitWebBackForwardList 37 * 38 * A history item consists out of a title and a uri. It can be part of the 39 * #WebKitWebBackForwardList and the global history. The global history is used 40 * for coloring the links of visited sites. #WebKitHistoryItem's constructed with 41 * #webkit_web_history_item_new and #webkit_web_history_item_new_with_data are 42 * automatically added to the global history. 43 * 44 * <informalexample><programlisting> 45 * /<!-- -->* Inject a visited page into the global history *<!-- -->/ 46 * webkit_web_history_item_new_with_data("http://www.gnome.org/", "GNOME: The Free Software Desktop Project"); 47 * webkit_web_history_item_new_with_data("http://www.webkit.org/", "The WebKit Open Source Project"); 48 * </programlisting></informalexample> 49 * 50 */ 51 52 using namespace WebKit; 53 54 struct _WebKitWebHistoryItemPrivate { 55 WebCore::HistoryItem* historyItem; 56 57 WebCore::CString title; 58 WebCore::CString alternateTitle; 59 WebCore::CString uri; 60 WebCore::CString originalUri; 61 62 gboolean disposed; 63 }; 64 65 #define WEBKIT_WEB_HISTORY_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_WEB_HISTORY_ITEM, WebKitWebHistoryItemPrivate)) 66 67 enum { 68 PROP_0, 69 70 PROP_TITLE, 71 PROP_ALTERNATE_TITLE, 72 PROP_URI, 73 PROP_ORIGINAL_URI, 74 PROP_LAST_VISITED_TIME 75 }; 76 77 G_DEFINE_TYPE(WebKitWebHistoryItem, webkit_web_history_item, G_TYPE_OBJECT); 78 79 static void webkit_web_history_item_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec); 80 81 static void webkit_web_history_item_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec); 82 83 GHashTable* webkit_history_items() 84 { 85 static GHashTable* historyItems = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); 86 return historyItems; 87 } 88 89 void webkit_history_item_add(WebKitWebHistoryItem* webHistoryItem, WebCore::HistoryItem* historyItem) 90 { 91 g_return_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem)); 92 93 GHashTable* table = webkit_history_items(); 94 g_hash_table_insert(table, historyItem, webHistoryItem); 95 } 96 97 static void webkit_web_history_item_dispose(GObject* object) 98 { 99 WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(object); 100 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; 101 102 if (!priv->disposed) { 103 WebCore::HistoryItem* item = core(webHistoryItem); 104 item->deref(); 105 priv->disposed = true; 106 } 107 108 G_OBJECT_CLASS(webkit_web_history_item_parent_class)->dispose(object); 109 } 110 111 static void webkit_web_history_item_finalize(GObject* object) 112 { 113 WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(object); 114 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; 115 116 priv->title = WebCore::CString(); 117 priv->alternateTitle = WebCore::CString(); 118 priv->uri = WebCore::CString(); 119 priv->originalUri = WebCore::CString(); 120 121 G_OBJECT_CLASS(webkit_web_history_item_parent_class)->finalize(object); 122 } 123 124 static void webkit_web_history_item_class_init(WebKitWebHistoryItemClass* klass) 125 { 126 GObjectClass* gobject_class = G_OBJECT_CLASS(klass); 127 128 gobject_class->dispose = webkit_web_history_item_dispose; 129 gobject_class->finalize = webkit_web_history_item_finalize; 130 gobject_class->set_property = webkit_web_history_item_set_property; 131 gobject_class->get_property = webkit_web_history_item_get_property; 132 133 webkit_init(); 134 135 /** 136 * WebKitWebHistoryItem:title: 137 * 138 * The title of the history item. 139 * 140 * Since: 1.0.2 141 */ 142 g_object_class_install_property(gobject_class, 143 PROP_TITLE, 144 g_param_spec_string( 145 "title", 146 _("Title"), 147 _("The title of the history item"), 148 NULL, 149 WEBKIT_PARAM_READABLE)); 150 151 /** 152 * WebKitWebHistoryItem:alternate-title: 153 * 154 * The alternate title of the history item. 155 * 156 * Since: 1.0.2 157 */ 158 g_object_class_install_property(gobject_class, 159 PROP_ALTERNATE_TITLE, 160 g_param_spec_string( 161 "alternate-title", 162 _("Alternate Title"), 163 _("The alternate title of the history item"), 164 NULL, 165 WEBKIT_PARAM_READWRITE)); 166 167 /** 168 * WebKitWebHistoryItem:uri: 169 * 170 * The URI of the history item. 171 * 172 * Since: 1.0.2 173 */ 174 g_object_class_install_property(gobject_class, 175 PROP_URI, 176 g_param_spec_string( 177 "uri", 178 _("URI"), 179 _("The URI of the history item"), 180 NULL, 181 WEBKIT_PARAM_READABLE)); 182 183 /** 184 * WebKitWebHistoryItem:original-uri: 185 * 186 * The original URI of the history item. 187 * 188 * Since: 1.0.2 189 */ 190 g_object_class_install_property(gobject_class, 191 PROP_ORIGINAL_URI, 192 g_param_spec_string( 193 "original-uri", 194 _("Original URI"), 195 _("The original URI of the history item"), 196 NULL, 197 WEBKIT_PARAM_READABLE)); 198 199 /** 200 * WebKitWebHistoryItem:last-visited-time: 201 * 202 * The time at which the history item was last visited. 203 * 204 * Since: 1.0.2 205 */ 206 g_object_class_install_property(gobject_class, 207 PROP_LAST_VISITED_TIME, 208 g_param_spec_double( 209 "last-visited-time", 210 _("Last visited Time"), 211 _("The time at which the history item was last visited"), 212 0, G_MAXDOUBLE, 0, 213 WEBKIT_PARAM_READABLE)); 214 215 g_type_class_add_private(gobject_class, sizeof(WebKitWebHistoryItemPrivate)); 216 } 217 218 static void webkit_web_history_item_init(WebKitWebHistoryItem* webHistoryItem) 219 { 220 webHistoryItem->priv = WEBKIT_WEB_HISTORY_ITEM_GET_PRIVATE(webHistoryItem); 221 } 222 223 static void webkit_web_history_item_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) 224 { 225 WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(object); 226 227 switch(prop_id) { 228 case PROP_ALTERNATE_TITLE: 229 webkit_web_history_item_set_alternate_title(webHistoryItem, g_value_get_string(value)); 230 break; 231 default: 232 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 233 break; 234 } 235 } 236 237 static void webkit_web_history_item_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) 238 { 239 WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(object); 240 241 switch (prop_id) { 242 case PROP_TITLE: 243 g_value_set_string(value, webkit_web_history_item_get_title(webHistoryItem)); 244 break; 245 case PROP_ALTERNATE_TITLE: 246 g_value_set_string(value, webkit_web_history_item_get_alternate_title(webHistoryItem)); 247 break; 248 case PROP_URI: 249 g_value_set_string(value, webkit_web_history_item_get_uri(webHistoryItem)); 250 break; 251 case PROP_ORIGINAL_URI: 252 g_value_set_string(value, webkit_web_history_item_get_original_uri(webHistoryItem)); 253 break; 254 case PROP_LAST_VISITED_TIME: 255 g_value_set_double(value, webkit_web_history_item_get_last_visited_time(webHistoryItem)); 256 break; 257 default: 258 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 259 break; 260 } 261 } 262 263 /* Helper function to create a new WebHistoryItem instance when needed */ 264 WebKitWebHistoryItem* webkit_web_history_item_new_with_core_item(PassRefPtr<WebCore::HistoryItem> historyItem) 265 { 266 return kit(historyItem); 267 } 268 269 270 /** 271 * webkit_web_history_item_new: 272 * 273 * Creates a new #WebKitWebHistoryItem instance 274 * 275 * Return value: the new #WebKitWebHistoryItem 276 */ 277 WebKitWebHistoryItem* webkit_web_history_item_new() 278 { 279 WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, NULL)); 280 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; 281 282 RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create(); 283 priv->historyItem = item.release().releaseRef(); 284 webkit_history_item_add(webHistoryItem, priv->historyItem); 285 286 return webHistoryItem; 287 } 288 289 /** 290 * webkit_web_history_item_new_with_data: 291 * @uri: the uri of the page 292 * @title: the title of the page 293 * 294 * Creates a new #WebKitWebHistoryItem with the given URI and title 295 * 296 * Return value: the new #WebKitWebHistoryItem 297 */ 298 WebKitWebHistoryItem* webkit_web_history_item_new_with_data(const gchar* uri, const gchar* title) 299 { 300 WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, NULL)); 301 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; 302 303 WebCore::KURL historyUri(WebCore::KURL(), uri); 304 WebCore::String historyTitle = WebCore::String::fromUTF8(title); 305 RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create(historyUri, historyTitle, 0); 306 priv->historyItem = item.release().releaseRef(); 307 webkit_history_item_add(webHistoryItem, priv->historyItem); 308 309 return webHistoryItem; 310 } 311 312 /** 313 * webkit_web_history_item_get_title: 314 * @web_history_item: a #WebKitWebHistoryItem 315 * 316 * Returns: the page title of @web_history_item 317 */ 318 G_CONST_RETURN gchar* webkit_web_history_item_get_title(WebKitWebHistoryItem* webHistoryItem) 319 { 320 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); 321 322 WebCore::HistoryItem* item = core(webHistoryItem); 323 324 g_return_val_if_fail(item, NULL); 325 326 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; 327 priv->title = item->title().utf8(); 328 329 return priv->title.data(); 330 } 331 332 /** 333 * webkit_web_history_item_get_alternate_title: 334 * @web_history_item: a #WebKitWebHistoryItem 335 * 336 * Returns the alternate title of @web_history_item 337 * 338 * Return value: the alternate title of @web_history_item 339 */ 340 G_CONST_RETURN gchar* webkit_web_history_item_get_alternate_title(WebKitWebHistoryItem* webHistoryItem) 341 { 342 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); 343 344 WebCore::HistoryItem* item = core(webHistoryItem); 345 346 g_return_val_if_fail(item, NULL); 347 348 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; 349 priv->alternateTitle = item->alternateTitle().utf8(); 350 351 return priv->alternateTitle.data(); 352 } 353 354 /** 355 * webkit_web_history_item_set_alternate_title: 356 * @web_history_item: a #WebKitWebHistoryItem 357 * @title: the alternate title for @this history item 358 * 359 * Sets an alternate title for @web_history_item 360 */ 361 void webkit_web_history_item_set_alternate_title(WebKitWebHistoryItem* webHistoryItem, const gchar* title) 362 { 363 g_return_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem)); 364 g_return_if_fail(title); 365 366 WebCore::HistoryItem* item = core(webHistoryItem); 367 368 item->setAlternateTitle(WebCore::String::fromUTF8(title)); 369 g_object_notify(G_OBJECT(webHistoryItem), "alternate-title"); 370 } 371 372 /** 373 * webkit_web_history_item_get_uri: 374 * @web_history_item: a #WebKitWebHistoryItem 375 * 376 * Returns the URI of @this 377 * 378 * Return value: the URI of @web_history_item 379 */ 380 G_CONST_RETURN gchar* webkit_web_history_item_get_uri(WebKitWebHistoryItem* webHistoryItem) 381 { 382 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); 383 384 WebCore::HistoryItem* item = core(WEBKIT_WEB_HISTORY_ITEM(webHistoryItem)); 385 386 g_return_val_if_fail(item, NULL); 387 388 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; 389 priv->uri = item->urlString().utf8(); 390 391 return priv->uri.data(); 392 } 393 394 /** 395 * webkit_web_history_item_get_original_uri: 396 * @web_history_item: a #WebKitWebHistoryItem 397 * 398 * Returns the original URI of @web_history_item. 399 * 400 * Return value: the original URI of @web_history_item 401 */ 402 G_CONST_RETURN gchar* webkit_web_history_item_get_original_uri(WebKitWebHistoryItem* webHistoryItem) 403 { 404 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); 405 406 WebCore::HistoryItem* item = core(WEBKIT_WEB_HISTORY_ITEM(webHistoryItem)); 407 408 g_return_val_if_fail(item, NULL); 409 410 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; 411 priv->originalUri = item->originalURLString().utf8(); 412 413 return webHistoryItem->priv->originalUri.data(); 414 } 415 416 /** 417 * webkit_web_history_item_get_last_visisted_time : 418 * @web_history_item: a #WebKitWebHistoryItem 419 * 420 * Returns the last time @web_history_item was visited 421 * 422 * Return value: the time in seconds this @web_history_item was last visited 423 */ 424 gdouble webkit_web_history_item_get_last_visited_time(WebKitWebHistoryItem* webHistoryItem) 425 { 426 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), 0); 427 428 WebCore::HistoryItem* item = core(WEBKIT_WEB_HISTORY_ITEM(webHistoryItem)); 429 430 g_return_val_if_fail(item, 0); 431 432 return item->lastVisitedTime(); 433 } 434 435 /** 436 * webkit_web_history_item_copy : 437 * @web_history_item: a #WebKitWebHistoryItem 438 * 439 * Makes a copy of the item for use with other WebView objects. 440 * 441 * Since: 1.1.18 442 * 443 * Return value: the new #WebKitWebHistoryItem. 444 */ 445 WebKitWebHistoryItem* webkit_web_history_item_copy(WebKitWebHistoryItem* self) 446 { 447 WebKitWebHistoryItemPrivate* selfPrivate = self->priv; 448 449 WebKitWebHistoryItem* item = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, 0)); 450 WebKitWebHistoryItemPrivate* priv = item->priv; 451 452 priv->title = selfPrivate->title; 453 priv->alternateTitle = selfPrivate->alternateTitle; 454 priv->uri = selfPrivate->uri; 455 priv->originalUri = selfPrivate->originalUri; 456 457 priv->historyItem = selfPrivate->historyItem->copy().releaseRef(); 458 459 return item; 460 } 461 462 /* private methods */ 463 464 G_CONST_RETURN gchar* webkit_web_history_item_get_target(WebKitWebHistoryItem* webHistoryItem) 465 { 466 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); 467 468 WebCore::HistoryItem* item = core(webHistoryItem); 469 470 g_return_val_if_fail(item, NULL); 471 472 WebCore::CString t = item->target().utf8(); 473 return g_strdup(t.data()); 474 } 475 476 gboolean webkit_web_history_item_is_target_item(WebKitWebHistoryItem* webHistoryItem) 477 { 478 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), false); 479 480 WebCore::HistoryItem* item = core(webHistoryItem); 481 482 g_return_val_if_fail(item, false); 483 484 return item->isTargetItem(); 485 } 486 487 GList* webkit_web_history_item_get_children(WebKitWebHistoryItem* webHistoryItem) 488 { 489 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); 490 491 WebCore::HistoryItem* item = core(webHistoryItem); 492 493 g_return_val_if_fail(item, NULL); 494 495 const WebCore::HistoryItemVector& children = item->children(); 496 if (!children.size()) 497 return NULL; 498 499 unsigned size = children.size(); 500 GList* kids = NULL; 501 for (unsigned i = 0; i < size; ++i) 502 kids = g_list_prepend(kids, kit(children[i].get())); 503 504 return g_list_reverse(kids); 505 } 506 507 WebCore::HistoryItem* WebKit::core(WebKitWebHistoryItem* webHistoryItem) 508 { 509 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); 510 511 return webHistoryItem->priv->historyItem; 512 } 513 514 WebKitWebHistoryItem* WebKit::kit(PassRefPtr<WebCore::HistoryItem> historyItem) 515 { 516 g_return_val_if_fail(historyItem, NULL); 517 518 RefPtr<WebCore::HistoryItem> item = historyItem; 519 GHashTable* table = webkit_history_items(); 520 WebKitWebHistoryItem* webHistoryItem = (WebKitWebHistoryItem*) g_hash_table_lookup(table, item.get()); 521 522 if (!webHistoryItem) { 523 webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, NULL)); 524 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; 525 526 priv->historyItem = item.release().releaseRef(); 527 webkit_history_item_add(webHistoryItem, priv->historyItem); 528 } 529 530 return webHistoryItem; 531 } 532 533