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 WebCore::KURL historyUri(uri);
301 WebCore::String historyTitle = WebCore::String::fromUTF8(title);
302
303 WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, NULL));
304 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv;
305
306 RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create(historyUri, historyTitle, 0);
307 priv->historyItem = item.release().releaseRef();
308 webkit_history_item_add(webHistoryItem, priv->historyItem);
309
310 return webHistoryItem;
311 }
312
313 /**
314 * webkit_web_history_item_get_title:
315 * @web_history_item: a #WebKitWebHistoryItem
316 *
317 * Returns: the page title of @web_history_item
318 */
webkit_web_history_item_get_title(WebKitWebHistoryItem * webHistoryItem)319 G_CONST_RETURN gchar* webkit_web_history_item_get_title(WebKitWebHistoryItem* webHistoryItem)
320 {
321 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL);
322
323 WebCore::HistoryItem* item = core(webHistoryItem);
324
325 g_return_val_if_fail(item, NULL);
326
327 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv;
328 priv->title = item->title().utf8();
329
330 return priv->title.data();
331 }
332
333 /**
334 * webkit_web_history_item_get_alternate_title:
335 * @web_history_item: a #WebKitWebHistoryItem
336 *
337 * Returns the alternate title of @web_history_item
338 *
339 * Return value: the alternate title of @web_history_item
340 */
webkit_web_history_item_get_alternate_title(WebKitWebHistoryItem * webHistoryItem)341 G_CONST_RETURN gchar* webkit_web_history_item_get_alternate_title(WebKitWebHistoryItem* webHistoryItem)
342 {
343 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL);
344
345 WebCore::HistoryItem* item = core(webHistoryItem);
346
347 g_return_val_if_fail(item, NULL);
348
349 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv;
350 priv->alternateTitle = item->alternateTitle().utf8();
351
352 return priv->alternateTitle.data();
353 }
354
355 /**
356 * webkit_web_history_item_set_alternate_title:
357 * @web_history_item: a #WebKitWebHistoryItem
358 * @title: the alternate title for @this history item
359 *
360 * Sets an alternate title for @web_history_item
361 */
webkit_web_history_item_set_alternate_title(WebKitWebHistoryItem * webHistoryItem,const gchar * title)362 void webkit_web_history_item_set_alternate_title(WebKitWebHistoryItem* webHistoryItem, const gchar* title)
363 {
364 g_return_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem));
365 g_return_if_fail(title);
366
367 WebCore::HistoryItem* item = core(webHistoryItem);
368
369 item->setAlternateTitle(WebCore::String::fromUTF8(title));
370 g_object_notify(G_OBJECT(webHistoryItem), "alternate-title");
371 }
372
373 /**
374 * webkit_web_history_item_get_uri:
375 * @web_history_item: a #WebKitWebHistoryItem
376 *
377 * Returns the URI of @this
378 *
379 * Return value: the URI of @web_history_item
380 */
webkit_web_history_item_get_uri(WebKitWebHistoryItem * webHistoryItem)381 G_CONST_RETURN gchar* webkit_web_history_item_get_uri(WebKitWebHistoryItem* webHistoryItem)
382 {
383 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL);
384
385 WebCore::HistoryItem* item = core(WEBKIT_WEB_HISTORY_ITEM(webHistoryItem));
386
387 g_return_val_if_fail(item, NULL);
388
389 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv;
390 priv->uri = item->urlString().utf8();
391
392 return priv->uri.data();
393 }
394
395 /**
396 * webkit_web_history_item_get_original_uri:
397 * @web_history_item: a #WebKitWebHistoryItem
398 *
399 * Returns the original URI of @web_history_item.
400 *
401 * Return value: the original URI of @web_history_item
402 */
webkit_web_history_item_get_original_uri(WebKitWebHistoryItem * webHistoryItem)403 G_CONST_RETURN gchar* webkit_web_history_item_get_original_uri(WebKitWebHistoryItem* webHistoryItem)
404 {
405 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL);
406
407 WebCore::HistoryItem* item = core(WEBKIT_WEB_HISTORY_ITEM(webHistoryItem));
408
409 g_return_val_if_fail(item, NULL);
410
411 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv;
412 priv->originalUri = item->originalURLString().utf8();
413
414 return webHistoryItem->priv->originalUri.data();
415 }
416
417 /**
418 * webkit_web_history_item_get_last_visisted_time :
419 * @web_history_item: a #WebKitWebHistoryItem
420 *
421 * Returns the last time @web_history_item was visited
422 *
423 * Return value: the time in seconds this @web_history_item was last visited
424 */
webkit_web_history_item_get_last_visited_time(WebKitWebHistoryItem * webHistoryItem)425 gdouble webkit_web_history_item_get_last_visited_time(WebKitWebHistoryItem* webHistoryItem)
426 {
427 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), 0);
428
429 WebCore::HistoryItem* item = core(WEBKIT_WEB_HISTORY_ITEM(webHistoryItem));
430
431 g_return_val_if_fail(item, 0);
432
433 return item->lastVisitedTime();
434 }
435
436 /* private methods */
437
webkit_web_history_item_get_target(WebKitWebHistoryItem * webHistoryItem)438 G_CONST_RETURN gchar* webkit_web_history_item_get_target(WebKitWebHistoryItem* webHistoryItem)
439 {
440 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL);
441
442 WebCore::HistoryItem* item = core(webHistoryItem);
443
444 g_return_val_if_fail(item, NULL);
445
446 WebCore::CString t = item->target().utf8();
447 return g_strdup(t.data());
448 }
449
webkit_web_history_item_is_target_item(WebKitWebHistoryItem * webHistoryItem)450 gboolean webkit_web_history_item_is_target_item(WebKitWebHistoryItem* webHistoryItem)
451 {
452 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), false);
453
454 WebCore::HistoryItem* item = core(webHistoryItem);
455
456 g_return_val_if_fail(item, false);
457
458 return item->isTargetItem();
459 }
460
webkit_web_history_item_get_children(WebKitWebHistoryItem * webHistoryItem)461 GList* webkit_web_history_item_get_children(WebKitWebHistoryItem* webHistoryItem)
462 {
463 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL);
464
465 WebCore::HistoryItem* item = core(webHistoryItem);
466
467 g_return_val_if_fail(item, NULL);
468
469 const WebCore::HistoryItemVector& children = item->children();
470 if (!children.size())
471 return NULL;
472
473 unsigned size = children.size();
474 GList* kids = NULL;
475 for (unsigned i = 0; i < size; ++i)
476 kids = g_list_prepend(kids, kit(children[i].get()));
477
478 return g_list_reverse(kids);
479 }
480
core(WebKitWebHistoryItem * webHistoryItem)481 WebCore::HistoryItem* WebKit::core(WebKitWebHistoryItem* webHistoryItem)
482 {
483 g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL);
484
485 return webHistoryItem->priv->historyItem;
486 }
487
kit(PassRefPtr<WebCore::HistoryItem> historyItem)488 WebKitWebHistoryItem* WebKit::kit(PassRefPtr<WebCore::HistoryItem> historyItem)
489 {
490 g_return_val_if_fail(historyItem, NULL);
491
492 RefPtr<WebCore::HistoryItem> item = historyItem;
493 GHashTable* table = webkit_history_items();
494 WebKitWebHistoryItem* webHistoryItem = (WebKitWebHistoryItem*) g_hash_table_lookup(table, item.get());
495
496 if (!webHistoryItem) {
497 webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, NULL));
498 WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv;
499
500 priv->historyItem = item.release().releaseRef();
501 webkit_history_item_add(webHistoryItem, priv->historyItem);
502 }
503
504 return webHistoryItem;
505 }
506
507