blob: 49c3a1a3b19d6cc8ddc71e77ba44942f887ad6ec [file] [log] [blame]
/*
Copyright (C) 2009-2010 ProFUSION embedded systems
Copyright (C) 2009-2010 Samsung Electronics
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include "ewk_history.h"
#include "BackForwardListImpl.h"
#include "CairoUtilitiesEfl.h"
#include "HistoryItem.h"
#include "IconDatabaseBase.h"
#include "Image.h"
#include "IntSize.h"
#include "Page.h"
#include "PageGroup.h"
#include "ewk_history_private.h"
#include "ewk_private.h"
#include <Eina.h>
#include <eina_safety_checks.h>
#include <wtf/text/CString.h>
struct _Ewk_History {
WebCore::BackForwardListImpl* core;
};
#define EWK_HISTORY_CORE_GET_OR_RETURN(history, core_, ...) \
if (!(history)) { \
CRITICAL("history is NULL."); \
return __VA_ARGS__; \
} \
if (!(history)->core) { \
CRITICAL("history->core is NULL."); \
return __VA_ARGS__; \
} \
if (!(history)->core->enabled()) { \
ERR("history->core is disabled!."); \
return __VA_ARGS__; \
} \
WebCore::BackForwardListImpl* core_ = (history)->core
struct _Ewk_History_Item {
WebCore::HistoryItem* core;
const char* title;
const char* alternateTitle;
const char* uri;
const char* originalUri;
};
#define EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core_, ...) \
if (!(item)) { \
CRITICAL("item is NULL."); \
return __VA_ARGS__; \
} \
if (!(item)->core) { \
CRITICAL("item->core is NULL."); \
return __VA_ARGS__; \
} \
WebCore::HistoryItem* core_ = (item)->core
static inline Eina_List* _ewk_history_item_list_get(const WebCore::HistoryItemVector& coreItems)
{
Eina_List* result = 0;
unsigned int size;
size = coreItems.size();
for (unsigned int i = 0; i < size; i++) {
Ewk_History_Item* item = ewk_history_item_new_from_core(coreItems[i].get());
if (item)
result = eina_list_append(result, item);
}
return result;
}
Eina_Bool ewk_history_clear(Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, false);
WebCore::Page* page = core->page();
if (page && page->groupPtr())
page->groupPtr()->removeVisitedLinks();
const int limit = ewk_history_limit_get(history);
ewk_history_limit_set(history, 0);
ewk_history_limit_set(history, limit);
return true;
}
Eina_Bool ewk_history_forward(Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, false);
if (core->forwardListCount() < 1)
return false;
core->goForward();
return true;
}
Eina_Bool ewk_history_back(Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, false);
if (core->backListCount() < 1)
return false;
core->goBack();
return true;
}
Eina_Bool ewk_history_history_item_add(Ewk_History* history, const Ewk_History_Item* item)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, history_core, false);
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, item_core, false);
history_core->addItem(item_core);
return true;
}
Eina_Bool ewk_history_history_item_set(Ewk_History* history, const Ewk_History_Item* item)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, history_core, false);
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, item_core, false);
history_core->goToItem(item_core);
return true;
}
Ewk_History_Item* ewk_history_history_item_back_get(const Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
return ewk_history_item_new_from_core(core->backItem());
}
Ewk_History_Item* ewk_history_history_item_current_get(const Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
WebCore::HistoryItem* currentItem = core->currentItem();
if (currentItem)
return ewk_history_item_new_from_core(currentItem);
return 0;
}
Ewk_History_Item* ewk_history_history_item_forward_get(const Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
return ewk_history_item_new_from_core(core->forwardItem());
}
Ewk_History_Item* ewk_history_history_item_nth_get(const Ewk_History* history, int index)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
return ewk_history_item_new_from_core(core->itemAtIndex(index));
}
Eina_Bool ewk_history_history_item_contains(const Ewk_History* history, const Ewk_History_Item* item)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, history_core, false);
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, item_core, false);
return history_core->containsItem(item_core);
}
Eina_List* ewk_history_forward_list_get(const Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
WebCore::HistoryItemVector items;
int limit = core->forwardListCount();
core->forwardListWithLimit(limit, items);
return _ewk_history_item_list_get(items);
}
Eina_List* ewk_history_forward_list_get_with_limit(const Ewk_History* history, int limit)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
WebCore::HistoryItemVector items;
core->forwardListWithLimit(limit, items);
return _ewk_history_item_list_get(items);
}
int ewk_history_forward_list_length(const Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
return core->forwardListCount();
}
Eina_List* ewk_history_back_list_get(const Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
WebCore::HistoryItemVector items;
int limit = core->backListCount();
core->backListWithLimit(limit, items);
return _ewk_history_item_list_get(items);
}
Eina_List* ewk_history_back_list_get_with_limit(const Ewk_History* history, int limit)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
WebCore::HistoryItemVector items;
core->backListWithLimit(limit, items);
return _ewk_history_item_list_get(items);
}
int ewk_history_back_list_length(const Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
return core->backListCount();
}
int ewk_history_limit_get(Ewk_History* history)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, 0);
return core->capacity();
}
Eina_Bool ewk_history_limit_set(const Ewk_History* history, int limit)
{
EWK_HISTORY_CORE_GET_OR_RETURN(history, core, false);
core->setCapacity(limit);
return true;
}
Ewk_History_Item* ewk_history_item_new_from_core(WebCore::HistoryItem* core)
{
Ewk_History_Item* item;
if (!core) {
ERR("WebCore::HistoryItem is NULL.");
return 0;
}
core->ref();
item = new Ewk_History_Item;
memset(item, 0, sizeof(*item));
item->core = core;
return item;
}
Ewk_History_Item* ewk_history_item_new(const char* uri, const char* title)
{
WTF::String historyUri = WTF::String::fromUTF8(uri);
WTF::String historyTitle = WTF::String::fromUTF8(title);
WTF::RefPtr<WebCore::HistoryItem> core = WebCore::HistoryItem::create(historyUri, historyTitle, 0);
Ewk_History_Item* item = ewk_history_item_new_from_core(core.release().leakRef());
return item;
}
static inline void _ewk_history_item_free(Ewk_History_Item* item, WebCore::HistoryItem* core)
{
core->deref();
delete item;
}
void ewk_history_item_free(Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core);
_ewk_history_item_free(item, core);
}
void ewk_history_item_list_free(Eina_List* history_items)
{
void* deleteItem;
EINA_LIST_FREE(history_items, deleteItem) {
Ewk_History_Item* item = (Ewk_History_Item*)deleteItem;
_ewk_history_item_free(item, item->core);
}
}
const char* ewk_history_item_title_get(const Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
// hide the following optimzation from outside
Ewk_History_Item* historyItem = const_cast<Ewk_History_Item*>(item);
eina_stringshare_replace(&historyItem->title, core->title().utf8().data());
return historyItem->title;
}
const char* ewk_history_item_title_alternate_get(const Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
// hide the following optimzation from outside
Ewk_History_Item* historyItem = const_cast<Ewk_History_Item*>(item);
eina_stringshare_replace(&historyItem->alternateTitle,
core->alternateTitle().utf8().data());
return historyItem->alternateTitle;
}
void ewk_history_item_title_alternate_set(Ewk_History_Item* item, const char* title)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core);
if (!eina_stringshare_replace(&item->alternateTitle, title))
return;
core->setAlternateTitle(WTF::String::fromUTF8(title));
}
const char* ewk_history_item_uri_get(const Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
// hide the following optimzation from outside
Ewk_History_Item* historyItem = const_cast<Ewk_History_Item*>((item));
eina_stringshare_replace(&historyItem->uri, core->urlString().utf8().data());
return historyItem->uri;
}
const char* ewk_history_item_uri_original_get(const Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
// hide the following optimzation from outside
Ewk_History_Item* historyItem = const_cast<Ewk_History_Item*>(item);
eina_stringshare_replace(&historyItem->originalUri,
core->originalURLString().utf8().data());
return historyItem->originalUri;
}
double ewk_history_item_time_last_visited_get(const Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0.0);
return core->lastVisitedTime();
}
cairo_surface_t* ewk_history_item_icon_surface_get(const Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
WebCore::NativeImagePtr icon = WebCore::iconDatabase().synchronousNativeIconForPageURL(core->url(), WebCore::IntSize(16, 16));
if (!icon)
ERR("icon is NULL.");
return icon ? icon->surface() : 0;
}
Evas_Object* ewk_history_item_icon_object_add(const Ewk_History_Item* item, Evas* canvas)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0);
WebCore::NativeImagePtr icon = WebCore::iconDatabase().synchronousNativeIconForPageURL(core->url(), WebCore::IntSize(16, 16));
if (!icon) {
ERR("icon is NULL.");
return 0;
}
cairo_surface_t* surface = icon->surface();
return surface ? WebCore::evasObjectFromCairoImageSurface(canvas, surface).leakRef() : 0;
}
Eina_Bool ewk_history_item_page_cache_exists(const Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, false);
return core->isInPageCache();
}
int ewk_history_item_visit_count(const Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, 0);
return core->visitCount();
}
Eina_Bool ewk_history_item_visit_last_failed(const Ewk_History_Item* item)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(item, core, true);
return core->lastVisitWasFailure();
}
/* internal methods ****************************************************/
/**
* @internal
*
* Creates history for given view. Called internally by ewk_view and
* should never be called from outside.
*
* @param core WebCore::BackForwardListImpl instance to use internally.
*
* @return newly allocated history instance or @c NULL on errors.
*/
Ewk_History* ewk_history_new(WebCore::BackForwardListImpl* core)
{
Ewk_History* history;
EINA_SAFETY_ON_NULL_RETURN_VAL(core, 0);
DBG("core=%p", core);
history = new Ewk_History;
history->core = core;
core->ref();
return history;
}
/**
* @internal
*
* Destroys previously allocated history instance. This is called
* automatically by ewk_view and should never be called from outside.
*
* @param history instance to free
*/
void ewk_history_free(Ewk_History* history)
{
DBG("history=%p", history);
history->core->deref();
delete history;
}
namespace EWKPrivate {
WebCore::HistoryItem* coreHistoryItem(const Ewk_History_Item* ewkHistoryItem)
{
EWK_HISTORY_ITEM_CORE_GET_OR_RETURN(ewkHistoryItem, core, 0);
return core;
}
} // namespace EWKPrivate