From 219f5dac32ac2c4ca158785514cdcc35cb3f18bf Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Thu, 25 Jul 2013 16:07:46 +0100 Subject: Add initial version of new cookie manager. --- desktop/cookie_manager.c | 758 +++++++++++++++++++++++++++++++++++++++++++++++ desktop/cookie_manager.h | 102 +++++++ 2 files changed, 860 insertions(+) create mode 100644 desktop/cookie_manager.c create mode 100644 desktop/cookie_manager.h diff --git a/desktop/cookie_manager.c b/desktop/cookie_manager.c new file mode 100644 index 000000000..0ec32b4e1 --- /dev/null +++ b/desktop/cookie_manager.c @@ -0,0 +1,758 @@ +/* + * Copyright 2013 Michael Drake + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Cookie Manager (implementation). + */ + + +#include + +#include "content/urldb.h" +#include "desktop/browser.h" +#include "desktop/cookie_manager.h" +#include "desktop/treeview.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "utils/log.h" + +enum cookie_manager_fields { + CM_NAME, + CM_CONTENT, + CM_DOMAIN, + CM_PATH, + CM_EXPIRES, + CM_LAST_USED, + CM_RESTRICTIONS, + CM_VERSION, + CM_PERSISTENT, + CM_DOMAIN_FOLDER, + N_FIELDS +}; + +struct cookie_manager_folder { + treeview_node *folder; + struct treeview_field_data data; +}; + +struct cookie_manager_ctx { + treeview *tree; + struct treeview_field_desc fields[N_FIELDS]; + bool built; +}; +struct cookie_manager_ctx cm_ctx; + +struct cookie_manager_entry { + bool user_delete; + + treeview_node *entry; + + struct treeview_field_data data[N_FIELDS - 1]; +}; + + +struct treeview_walk_ctx { + const char *title; + struct cookie_manager_folder *folder; + struct cookie_manager_entry *entry; +}; +/** Callback for treeview_walk */ +static nserror cookie_manager_walk_cb(void *ctx, void *node_data, + enum treeview_node_type type, bool *abort) +{ + struct treeview_walk_ctx *tw = ctx; + + if (type == TREE_NODE_ENTRY) { + struct cookie_manager_entry *entry = node_data; + + if (strcmp(tw->title, entry->data[CM_NAME].value) == 0) { + /* Found what we're looking for */ + tw->entry = entry; + *abort = true; + } + + } else if (type == TREE_NODE_FOLDER) { + struct cookie_manager_folder *folder = node_data; + + if (strcmp(tw->title, folder->data.value) == 0) { + /* Found what we're looking for */ + tw->folder = folder; + *abort = true; + } + } + + return NSERROR_OK; +} +/** + * Find a cookie entry in the cookie manager's treeview + * + * \param root Search root node, or NULL to search from tree's root + * \param title ID of the node to look for + * \param found Updated to the matching node's cookie maanger entry + * \return NSERROR_OK on success, appropriate error otherwise + */ +static nserror cookie_manager_find_entry(treeview_node *root, + const char *title, struct cookie_manager_entry **found) +{ + nserror err; + struct treeview_walk_ctx tw = { + .title = title, + .folder = NULL, + .entry = NULL + }; + + err = treeview_walk(cm_ctx.tree, root, cookie_manager_walk_cb, &tw, + TREE_NODE_ENTRY); + if (err != NSERROR_OK) + return err; + + *found = tw.entry; + + return NSERROR_OK; +} +/** + * Find a cookie domain folder in the cookie manager's treeview + * + * \param root Search root node, or NULL to search from tree's root + * \param title ID of the node to look for + * \param found Updated to the matching node's cookie maanger folder + * \return NSERROR_OK on success, appropriate error otherwise + */ +static nserror cookie_manager_find_folder(treeview_node *root, + const char *title, struct cookie_manager_folder **found) +{ + nserror err; + struct treeview_walk_ctx tw = { + .title = title, + .folder = NULL, + .entry = NULL + }; + + err = treeview_walk(cm_ctx.tree, root, cookie_manager_walk_cb, &tw, + TREE_NODE_FOLDER); + if (err != NSERROR_OK) + return err; + + *found = tw.folder; + + return NSERROR_OK; +} + + +/** + * Free a cookie manager entry's treeview field data. + * + * \param e Cookie manager entry to free data from + */ +static void cookie_manager_free_treeview_field_data( + struct cookie_manager_entry *e) +{ + /* Eww */ + free((void *)e->data[CM_NAME].value); + free((void *)e->data[CM_CONTENT].value); + free((void *)e->data[CM_DOMAIN].value); + free((void *)e->data[CM_PATH].value); + free((void *)e->data[CM_EXPIRES].value); + free((void *)e->data[CM_LAST_USED].value); + free((void *)e->data[CM_RESTRICTIONS].value); + free((void *)e->data[CM_VERSION].value); + free((void *)e->data[CM_PERSISTENT].value); +} + + +/** + * Set a cookie manager entry's data from the cookie_data. + * + * \param e Cookie manager entry to set up + * \param data Data associated with entry's cookie + * \return NSERROR_OK on success, appropriate error otherwise + */ +static nserror cookie_manager_set_treeview_field_data( + struct cookie_manager_entry *e, + const struct cookie_data *data) +{ + const char *temp; + const char *date; + char *date2; + char buffer[32]; + + assert(e != NULL); + assert(data != NULL); + + /* Set the Name text */ + temp = data->name; + e->data[CM_NAME].field = cm_ctx.fields[CM_NAME].field; + e->data[CM_NAME].value = strdup(temp); + e->data[CM_NAME].value_len = (e->data[CM_NAME].value != NULL) ? + strlen(temp) : 0; + + /* Set the Content text */ + temp = data->value; + e->data[CM_CONTENT].field = cm_ctx.fields[CM_CONTENT].field; + e->data[CM_CONTENT].value = strdup(temp); + e->data[CM_CONTENT].value_len = (e->data[CM_CONTENT].value != NULL) ? + strlen(temp) : 0; + + /* Set the Domain text */ + temp = data->domain; + e->data[CM_DOMAIN].field = cm_ctx.fields[CM_DOMAIN].field; + e->data[CM_DOMAIN].value = strdup(temp); + e->data[CM_DOMAIN].value_len = (e->data[CM_DOMAIN].value != NULL) ? + strlen(temp) : 0; + + /* Set the Path text */ + temp = data->path; + e->data[CM_PATH].field = cm_ctx.fields[CM_PATH].field; + e->data[CM_PATH].value = strdup(temp); + e->data[CM_PATH].value_len = (e->data[CM_PATH].value != NULL) ? + strlen(temp) : 0; + + /* Set the Expires date text */ + date = ctime(&data->expires); + date2 = strdup(date); + if (date2 != NULL) { + assert(date2[24] == '\n'); + date2[24] = '\0'; + } + + e->data[CM_EXPIRES].field = cm_ctx.fields[CM_EXPIRES].field; + e->data[CM_EXPIRES].value = date2; + e->data[CM_EXPIRES].value_len = (date2 != NULL) ? 24 : 0; + + /* Set the Last used date text */ + date = ctime(&data->last_used); + date2 = strdup(date); + if (date2 != NULL) { + assert(date2[24] == '\n'); + date2[24] = '\0'; + } + + e->data[CM_LAST_USED].field = cm_ctx.fields[CM_LAST_USED].field; + e->data[CM_LAST_USED].value = date2; + e->data[CM_LAST_USED].value_len = (date2 != NULL) ? 24 : 0; + + /* Set the Restrictions text */ + if (data->secure && data->http_only) + temp = "Secure hosts via https only"; + else if (data->secure) + temp = "Secure hosts only"; + else if (data->http_only) + temp = "HTTP connections only"; + else + temp = "None"; + + e->data[CM_RESTRICTIONS].field = cm_ctx.fields[CM_RESTRICTIONS].field; + e->data[CM_RESTRICTIONS].value = strdup(temp); + e->data[CM_RESTRICTIONS].value_len = + (e->data[CM_RESTRICTIONS].value != NULL) ? + strlen(temp) : 0; + + /* Set the Version text */ + snprintf(buffer, sizeof(buffer), "TreeVersion%i", data->version); + temp = messages_get(buffer); + e->data[CM_VERSION].field = cm_ctx.fields[CM_VERSION].field; + e->data[CM_VERSION].value = strdup(temp); + e->data[CM_VERSION].value_len = (e->data[CM_VERSION].value != NULL) ? + strlen(temp) : 0; + + /* Set the Persistent text */ + temp = data->no_destroy ? messages_get("Yes") : messages_get("No"); + e->data[CM_PERSISTENT].field = cm_ctx.fields[CM_PERSISTENT].field; + e->data[CM_PERSISTENT].value = strdup(temp); + e->data[CM_PERSISTENT].value_len = + (e->data[CM_PERSISTENT].value != NULL) ? + strlen(temp) : 0; + + return NSERROR_OK; +} + + +/** + * Creates an empty tree entry for a cookie, and links it into the tree. + * + * All information is copied from the cookie_data, and as such can + * be edited and should be freed. + * + * \param parent the node to link to + * \param data the cookie data to use + * \return NSERROR_OK on success, appropriate error otherwise + */ +static nserror cookie_manager_create_cookie_node( + struct cookie_manager_folder *parent, + const struct cookie_data *data) +{ + nserror err; + struct cookie_manager_entry *cookie; + + /* Create new cookie manager entry */ + cookie = malloc(sizeof(struct cookie_manager_entry)); + if (cookie == NULL) { + return NSERROR_NOMEM; + } + + cookie->user_delete = false; + + err = cookie_manager_set_treeview_field_data(cookie, data); + if (err != NSERROR_OK) { + free(cookie); + return err; + } + + err = treeview_create_node_entry(cm_ctx.tree, &(cookie->entry), + parent->folder, TREE_REL_FIRST_CHILD, + cookie->data, cookie, + cm_ctx.built ? TREE_CREATE_NONE : + TREE_CREATE_SUPPRESS_RESIZE); + if (err != NSERROR_OK) { + cookie_manager_free_treeview_field_data(cookie); + free(cookie); + return err; + } + + return NSERROR_OK; +} + + +/** + * Updates a cookie manager entry for updated cookie_data. + * + * All information is copied from the cookie_data, and as such can + * be edited and should be freed. + * + * \param e the entry to update + * \param data the cookie data to use + * \return NSERROR_OK on success, appropriate error otherwise + */ +static nserror cookie_manager_update_cookie_node( + struct cookie_manager_entry *e, + const struct cookie_data *data) +{ + nserror err; + + assert(e != NULL); + + /* Reset to defaults */ + e->user_delete = false; + cookie_manager_free_treeview_field_data(e); + + /* Set new field values from the cookie_data */ + err = cookie_manager_set_treeview_field_data(e, data); + if (err != NSERROR_OK) { + return err; + } + + /* Update the treeview */ + err = treeview_update_node_entry(cm_ctx.tree, e->entry, e->data, e); + if (err != NSERROR_OK) { + return err; + } + + return NSERROR_OK; +} + + +/** + * Creates an empty tree folder for a cookie domain, and links it into the tree. + * + * All information is copied from the cookie_data, and as such can + * be edited and should be freed. + * + * \param folder updated to the new folder + * \param data the cookie data to use + * \return NSERROR_OK on success, appropriate error otherwise + */ +static nserror cookie_manager_create_domain_folder( + struct cookie_manager_folder **folder, + const struct cookie_data *data) +{ + nserror err; + struct cookie_manager_folder *f; + + /* Create new cookie manager entry */ + f = malloc(sizeof(struct cookie_manager_folder)); + if (f == NULL) { + return NSERROR_NOMEM; + } + + f->data.field = cm_ctx.fields[N_FIELDS - 1].field; + f->data.value = strdup(data->domain); + f->data.value_len = (f->data.value != NULL) ? + strlen(data->domain) : 0; + + err = treeview_create_node_folder(cm_ctx.tree, &(f->folder), + NULL, TREE_REL_FIRST_CHILD, &f->data, f, + cm_ctx.built ? TREE_CREATE_NONE : + TREE_CREATE_SUPPRESS_RESIZE); + if (err != NSERROR_OK) { + free((void *)f->data.value); + free(f); + return err; + } + + *folder = f; + + return NSERROR_OK; +} + + +/* exported interface documented in cookie_manager.h */ +bool cookie_manager_add(const struct cookie_data *data) +{ + struct cookie_manager_folder *parent = NULL; + struct cookie_manager_entry *cookie = NULL; + nserror err; + + assert(data != NULL); + + /* If we don't have a cookie manager at the moment, just return true */ + if (cm_ctx.tree == NULL) + return true; + + err = cookie_manager_find_folder(NULL, data->domain, &parent); + if (err != NSERROR_OK) { + return false; + } + + if (parent == NULL) { + /* Need to create domain directory */ + err = cookie_manager_create_domain_folder(&parent, data); + if (err != NSERROR_OK || parent == NULL) + return false; + } + + /* Create cookie node */ + err = cookie_manager_find_entry(parent->folder, data->name, &cookie); + if (err != NSERROR_OK) + return false; + + if (cookie == NULL) { + err = cookie_manager_create_cookie_node(parent, data); + } else { + err = cookie_manager_update_cookie_node(cookie, data); + } + if (err != NSERROR_OK) + return false; + + return true; +} + + +/* exported interface documented in cookie_manager.h */ +void cookie_manager_remove(const struct cookie_data *data) +{ + struct cookie_manager_folder *parent = NULL; + struct cookie_manager_entry *cookie = NULL; + nserror err; + + assert(data != NULL); + + /* If we don't have a cookie manager at the moment, just return */ + if (cm_ctx.tree == NULL) + return; + + err = cookie_manager_find_folder(NULL, data->domain, &parent); + if (err != NSERROR_OK || parent == NULL) { + /* Nothing to delete */ + return; + } + + err = cookie_manager_find_entry(parent->folder, data->name, &cookie); + if (err != NSERROR_OK || cookie == NULL) { + /* Nothing to delete */ + return; + } + + /* Delete the node */ + treeview_delete_node(cm_ctx.tree, cookie->entry); +} + + +/** + * Initialise the treeview entry feilds + * + * \return true on success, false on memory exhaustion + */ +static nserror cookie_manager_init_entry_fields(void) +{ + int i; + const char *label; + + for (i = 0; i < N_FIELDS; i++) + cm_ctx.fields[i].field = NULL; + + cm_ctx.fields[CM_NAME].flags = TREE_FLAG_DEFAULT; + label = "TreeviewLabelName"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_NAME].field) != + lwc_error_ok) { + goto error; + } + + cm_ctx.fields[CM_CONTENT].flags = TREE_FLAG_SHOW_NAME; + label = "TreeviewLabelContent"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_CONTENT].field) != + lwc_error_ok) { + goto error; + } + + cm_ctx.fields[CM_DOMAIN].flags = TREE_FLAG_SHOW_NAME; + label = "TreeviewLabelDomain"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_DOMAIN].field) != + lwc_error_ok) { + goto error; + } + + cm_ctx.fields[CM_PATH].flags = TREE_FLAG_SHOW_NAME; + label = "TreeviewLabelPath"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_PATH].field) != + lwc_error_ok) { + goto error; + } + + cm_ctx.fields[CM_EXPIRES].flags = TREE_FLAG_SHOW_NAME; + label = "TreeviewLabelExpires"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_EXPIRES].field) != + lwc_error_ok) { + goto error; + } + + cm_ctx.fields[CM_LAST_USED].flags = TREE_FLAG_SHOW_NAME; + label = "TreeviewLabelLastUsed"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_LAST_USED].field) != + lwc_error_ok) { + goto error; + } + + cm_ctx.fields[CM_RESTRICTIONS].flags = TREE_FLAG_SHOW_NAME; + label = "TreeviewLabelRestrictions"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_RESTRICTIONS].field) != + lwc_error_ok) { + goto error; + } + + cm_ctx.fields[CM_VERSION].flags = TREE_FLAG_SHOW_NAME; + label = "TreeviewLabelVersion"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_VERSION].field) != + lwc_error_ok) { + goto error; + } + + cm_ctx.fields[CM_PERSISTENT].flags = TREE_FLAG_SHOW_NAME; + label = "TreeviewLabelPersistent"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_PERSISTENT].field) != + lwc_error_ok) { + goto error; + } + + cm_ctx.fields[CM_DOMAIN_FOLDER].flags = TREE_FLAG_DEFAULT; + label = "TreeviewLabelDomainFolder"; + label = messages_get(label); + if (lwc_intern_string(label, strlen(label), + &cm_ctx.fields[CM_DOMAIN_FOLDER].field) != + lwc_error_ok) { + return false; + } + + return NSERROR_OK; + +error: + for (i = 0; i < N_FIELDS; i++) + if (cm_ctx.fields[i].field != NULL) + lwc_string_unref(cm_ctx.fields[i].field); + + return NSERROR_UNKNOWN; +} + +/** + * Delete cookie manager entries (and optionally delete from urldb) + * + * \param e Cookie manager entry to delete. + */ +static void cookie_manager_delete_entry(struct cookie_manager_entry *e) +{ + const char *domain; + const char *path; + const char *name; + + if (e->user_delete) { + /* Delete the cookie from URLdb */ + domain = e->data[CM_DOMAIN].value; + path = e->data[CM_PATH].value; + name = e->data[CM_NAME].value; + + if ((domain != NULL) && (path != NULL) && (name != NULL)) { + + urldb_delete_cookie(domain, path, name); + } else { + LOG(("Delete cookie fail: " + "need domain, path, and name.")); + } + } + + /* Delete the cookie manager entry */ + cookie_manager_free_treeview_field_data(e); + free(e); +} + + +static nserror cookie_manager_tree_node_folder_cb( + struct treeview_node_msg msg, void *data) +{ + struct cookie_manager_folder *f = data; + + switch (msg.msg) { + case TREE_MSG_NODE_DELETE: + free(f); + break; + + case TREE_MSG_NODE_EDIT: + break; + + case TREE_MSG_NODE_LAUNCH: + break; + } + + return NSERROR_OK; +} +static nserror cookie_manager_tree_node_entry_cb( + struct treeview_node_msg msg, void *data) +{ + struct cookie_manager_entry *e = data; + + switch (msg.msg) { + case TREE_MSG_NODE_DELETE: + e->entry = NULL; + e->user_delete = msg.data.delete.user; + cookie_manager_delete_entry(e); + break; + + case TREE_MSG_NODE_EDIT: + break; + + case TREE_MSG_NODE_LAUNCH: + break; + } + return NSERROR_OK; +} +struct treeview_callback_table cm_tree_cb_t = { + .folder = cookie_manager_tree_node_folder_cb, + .entry = cookie_manager_tree_node_entry_cb +}; + + +/* Exported interface, documented in cookie_manager.h */ +nserror cookie_manager_init(struct core_window_callback_table *cw_t, + void *core_window_handle) +{ + nserror err; + + LOG(("Generating cookie manager data")); + + /* Init. cookie manager treeview entry fields */ + err = cookie_manager_init_entry_fields(); + if (err != NSERROR_OK) { + cm_ctx.tree = NULL; + return err; + } + + /* Create the cookie manager treeview */ + err = treeview_create(&cm_ctx.tree, &cm_tree_cb_t, + N_FIELDS, cm_ctx.fields, + cw_t, core_window_handle, + TREEVIEW_NO_MOVES | TREEVIEW_DEL_EMPTY_DIRS); + if (err != NSERROR_OK) { + cm_ctx.tree = NULL; + return err; + } + + /* Load the cookies */ + urldb_iterate_cookies(cookie_manager_add); + + /* Cookie manager is built + * We suppress the treeview height callback on entry insertion before + * the treeview is built. */ + cm_ctx.built = true; + + LOG(("Generated cookie manager data")); + + return NSERROR_OK; +} + + +/* Exported interface, documented in cookie_manager.h */ +nserror cookie_manager_fini(void) +{ + int i; + nserror err; + + LOG(("Finalising cookie manager")); + + cm_ctx.built = false; + + /* Destroy the cookie manager treeview */ + err = treeview_destroy(cm_ctx.tree); + + /* Free cookie manager treeview entry fields */ + for (i = 0; i < N_FIELDS; i++) + if (cm_ctx.fields[i].field != NULL) + lwc_string_unref(cm_ctx.fields[i].field); + + LOG(("Finalised cookie manager")); + + return err; +} + + +/* Exported interface, documented in cookie_manager.h */ +void cookie_manager_redraw(int x, int y, struct rect *clip, + const struct redraw_context *ctx) +{ + treeview_redraw(cm_ctx.tree, x, y, clip, ctx); +} + + +/* Exported interface, documented in cookie_manager.h */ +void cookie_manager_mouse_action(browser_mouse_state mouse, int x, int y) +{ + treeview_mouse_action(cm_ctx.tree, mouse, x, y); +} + + +/* Exported interface, documented in cookie_manager.h */ +void cookie_manager_keypress(uint32_t key) +{ + treeview_keypress(cm_ctx.tree, key); +} + diff --git a/desktop/cookie_manager.h b/desktop/cookie_manager.h new file mode 100644 index 000000000..724923677 --- /dev/null +++ b/desktop/cookie_manager.h @@ -0,0 +1,102 @@ +/* + * Copyright 2013 Michael Drake + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * Cookie Manager (interface). + */ + +#ifndef _NETSURF_DESKTOP_COOKIE_MANAGER_H_ +#define _NETSURF_DESKTOP_COOKIE_MANAGER_H_ + +#include + +#include "desktop/core_window.h" + +struct cookie_data; + +/** + * Initialise the cookie manager. + * + * This iterates through the URL database, enumerating the cookies and + * creates a treeview. + * + * This must be called before any other cookie_manager_* function. + * + * \param cw_t Callback table for core_window containing the treeview + * \param cw The core_window in which the treeview is shown + * \return NSERROR_OK on success, appropriate error otherwise + */ +nserror cookie_manager_init(struct core_window_callback_table *cw_t, + void *core_window_handle); + +/** + * Finalise the cookie manager. + * + * This destroys the cookie manager treeview and the cookie manager module's + * internal data. After calling this if the cookie manager is required again, + * cookie_manager_init must be called. + * + * \return NSERROR_OK on success, appropriate error otherwise + */ +nserror cookie_manager_fini(void); + +/** + * Add/update a cookie to the viewer. (Called by urldb.) + * + * \param data Data of cookie being added/updated. + * \return true (for urldb_iterate_entries) + */ +bool cookie_manager_add(const struct cookie_data *data); + +/** + * Remove a cookie from viewer. (Called by urldb.) + * + * \param data Data of cookie being removed. + */ +void cookie_manager_remove(const struct cookie_data *data); + +/** + * Redraw the cookies manager. + * + * \param x X coordinate to render treeview at + * \param x Y coordinate to render treeview at + * \param clip Current clip rectangle (wrt tree origin) + * \param ctx Current redraw context + */ +void cookie_manager_redraw(int x, int y, struct rect *clip, + const struct redraw_context *ctx); + +/** + * Handles all kinds of mouse action + * + * \param mouse The current mouse state + * \param x X coordinate + * \param y Y coordinate + */ +void cookie_manager_mouse_action(browser_mouse_state mouse, int x, int y); + + +/** + * Key press handling. + * + * \param key The ucs4 character codepoint + * \return true if the keypress is dealt with, false otherwise. + */ +void cookie_manager_keypress(uint32_t key); + +#endif -- cgit v1.2.3