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
webkit_history_items()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
webkit_history_item_add(WebKitWebHistoryItem * webHistoryItem,WebCore::HistoryItem * historyItem)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
webkit_web_history_item_dispose(GObject * object)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
webkit_web_history_item_finalize(GObject * object)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
webkit_web_history_item_class_init(WebKitWebHistoryItemClass * klass)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
webkit_web_history_item_init(WebKitWebHistoryItem * webHistoryItem)218 static void webkit_web_history_item_init(WebKitWebHistoryItem* webHistoryItem)
219 {
220 webHistoryItem->priv = WEBKIT_WEB_HISTORY_ITEM_GET_PRIVATE(webHistoryItem);
221 }
222
webkit_web_history_item_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)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
webkit_web_history_item_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)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 */
webkit_web_history_item_new_with_core_item(PassRefPtr<WebCore::HistoryItem> historyItem)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 */
webkit_web_history_item_new()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 */
webkit_web_history_item_new_with_data(const gchar * uri,const gchar * title)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 */
webkit_web_history_item_get_title(WebKitWebHistoryItem * webHistoryItem)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 */
webkit_web_history_item_get_alternate_title(WebKitWebHistoryItem * webHistoryItem)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 */
webkit_web_history_item_set_alternate_title(WebKitWebHistoryItem * webHistoryItem,const gchar * title)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 */
webkit_web_history_item_get_uri(WebKitWebHistoryItem * webHistoryItem)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 */
webkit_web_history_item_get_original_uri(WebKitWebHistoryItem * webHistoryItem)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 */
webkit_web_history_item_get_last_visited_time(WebKitWebHistoryItem * webHistoryItem)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 */
webkit_web_history_item_copy(WebKitWebHistoryItem * self)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
webkit_web_history_item_get_target(WebKitWebHistoryItem * webHistoryItem)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
webkit_web_history_item_is_target_item(WebKitWebHistoryItem * webHistoryItem)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
webkit_web_history_item_get_children(WebKitWebHistoryItem * webHistoryItem)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
core(WebKitWebHistoryItem * webHistoryItem)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
kit(PassRefPtr<WebCore::HistoryItem> historyItem)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