void theme_install_close(wimp_w w) { if (theme_install_content) hlcache_handle_release(theme_install_content); theme_install_content = NULL; }
/** * Handler for imported stylesheet events * * \param handle Handle for stylesheet * \param event Event object * \param pw Callback context * \return NSERROR_OK on success, appropriate error otherwise */ nserror nscss_import(hlcache_handle *handle, const hlcache_event *event, void *pw) { nscss_import_ctx *ctx = pw; css_error error = CSS_OK; #ifdef NSCSS_IMPORT_TRACE LOG(("Event %d for %p (%p)", event->type, handle, ctx)); #endif assert(ctx->css->imports[ctx->index].c == handle); switch (event->type) { case CONTENT_MSG_DONE: error = nscss_import_complete(ctx); break; case CONTENT_MSG_ERROR: hlcache_handle_release(handle); ctx->css->imports[ctx->index].c = NULL; error = nscss_import_complete(ctx); /* Already released handle */ break; default: break; } /* Preserve out-of-memory. Anything else is OK */ return error == CSS_NOMEM ? NSERROR_NOMEM : NSERROR_OK; }
static bool html_css_process_modified_style(html_content *c, struct html_stylesheet *s) { hlcache_handle *sheet = NULL; nserror error; error = html_stylesheet_from_domnode(c, s->node, &sheet); if (error != NSERROR_OK) { LOG("Failed to update sheet"); content_broadcast_errorcode(&c->base, error); return false; } if (sheet != NULL) { LOG("Updating sheet %p with %p", s->sheet, sheet); if (s->sheet != NULL) { switch (content_get_status(s->sheet)) { case CONTENT_STATUS_DONE: break; default: hlcache_handle_abort(s->sheet); c->base.active--; LOG("%d fetches active", c->base.active); } hlcache_handle_release(s->sheet); } s->sheet = sheet; } s->modified = false; return true; }
/** * Callback for defer scripts */ static nserror convert_script_defer_cb(hlcache_handle *script, const hlcache_event *event, void *pw) { html_content *parent = pw; unsigned int i; struct html_script *s; /* Find script */ for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) { if (s->type == HTML_SCRIPT_DEFER && s->data.handle == script) break; } assert(i != parent->scripts_count); switch (event->type) { case CONTENT_MSG_LOADING: break; case CONTENT_MSG_READY: break; case CONTENT_MSG_DONE: LOG(("script %d done '%s'", i, nsurl_access(hlcache_handle_get_url(script)))); parent->base.active--; LOG(("%d fetches active", parent->base.active)); break; case CONTENT_MSG_ERROR: LOG(("script %s failed: %s", nsurl_access(hlcache_handle_get_url(script)), event->data.error)); hlcache_handle_release(script); s->data.handle = NULL; parent->base.active--; LOG(("%d fetches active", parent->base.active)); content_add_error(&parent->base, "?", 0); break; case CONTENT_MSG_STATUS: break; default: assert(0); } /* if there are no active fetches remaining begin post parse * conversion */ if (html_can_begin_conversion(parent)) { html_begin_conversion(parent); } return NSERROR_OK; }
void tree_url_node_cleanup() { struct icon_entry *entry; tun_users--; if (tun_users > 0) return; if (!initialised) return; initialised = false; hlcache_handle_release(folder_icon); entry = icon_table; do { hlcache_handle_release(entry->icon); ++entry; } while (entry->type != CONTENT_HTML); }
static nserror html_convert_css_callback(hlcache_handle *css, const hlcache_event *event, void *pw) { html_content *parent = pw; unsigned int i; struct html_stylesheet *s; /* Find sheet */ for (i = 0, s = parent->stylesheets; i != parent->stylesheet_count; i++, s++) { if (s->sheet == css) break; } assert(i != parent->stylesheet_count); switch (event->type) { case CONTENT_MSG_DONE: LOG("done stylesheet slot %d '%s'", i, nsurl_access(hlcache_handle_get_url(css))); parent->base.active--; LOG("%d fetches active", parent->base.active); break; case CONTENT_MSG_ERROR: LOG("stylesheet %s failed: %s", nsurl_access(hlcache_handle_get_url(css)), event->data.error); hlcache_handle_release(css); s->sheet = NULL; parent->base.active--; LOG("%d fetches active", parent->base.active); content_add_error(&parent->base, "?", 0); break; case CONTENT_MSG_POINTER: /* Really don't want this to continue after the switch */ return NSERROR_OK; default: break; } if (html_can_begin_conversion(parent)) { html_begin_conversion(parent); } return NSERROR_OK; }
/** * Memory allocated during printing is being freed here. * * \param content The original content * \param printer The printer interface for the printer to be used * \param settings The print settings to use. * \return true if successful, false otherwise */ bool print_cleanup(hlcache_handle *content, const struct printer *printer, struct print_settings *settings) { printer->print_end(); html_redraw_printing = false; if (printed_content) { hlcache_handle_release(printed_content); } free((void *)settings->output); free(settings); return true; }
static bool html_replace_object(struct content_html_object *object, nsurl *url) { html_content *c; hlcache_child_context child; html_content *page; nserror error; assert(object != NULL); assert(object->box != NULL); c = (html_content *) object->parent; child.charset = c->encoding; child.quirks = c->base.quirks; if (object->content != NULL) { /* remove existing object */ if (content_get_status(object->content) != CONTENT_STATUS_DONE) { c->base.active--; LOG("%d fetches active", c->base.active); } hlcache_handle_release(object->content); object->content = NULL; object->box->object = NULL; } /* initialise fetch */ error = hlcache_handle_retrieve(url, HLCACHE_RETRIEVE_SNIFF_TYPE, content_get_url(&c->base), NULL, html_object_callback, object, &child, object->permitted_types, &object->content); if (error != NSERROR_OK) return false; for (page = c; page != NULL; page = page->page) { page->base.active++; LOG("%d fetches active", c->base.active); page->base.status = CONTENT_STATUS_READY; } return true; }
/* exported interface documented in render/html_internal.h */ nserror html_css_free_stylesheets(html_content *html) { unsigned int i; guit->misc->schedule(-1, html_css_process_modified_styles, html); for (i = 0; i != html->stylesheet_count; i++) { if (html->stylesheets[i].sheet != NULL) { hlcache_handle_release(html->stylesheets[i].sheet); } if (html->stylesheets[i].node != NULL) { dom_node_unref(html->stylesheets[i].node); } } free(html->stylesheets); return NSERROR_OK; }
nserror html_object_free_objects(html_content *html) { while (html->object_list != NULL) { struct content_html_object *victim = html->object_list; if (victim->content != NULL) { LOG("object %p", victim->content); if (content_get_type(victim->content) == CONTENT_HTML) { guit->misc->schedule(-1, html_object_refresh, victim); } hlcache_handle_release(victim->content); } html->object_list = victim->next; free(victim); } return NSERROR_OK; }
/** * Clean up CSS data * * \param c CSS data to clean up */ static void nscss_destroy_css_data(struct content_css_data *c) { uint32_t i; for (i = 0; i < c->import_count; i++) { if (c->imports[i].c != NULL) { hlcache_handle_release(c->imports[i].c); } c->imports[i].c = NULL; } free(c->imports); if (c->sheet != NULL) { css_stylesheet_destroy(c->sheet); c->sheet = NULL; } free(c->charset); }
static nserror theme_install_callback(hlcache_handle *c, const hlcache_event *event, void *pw) { switch (event->type) { case CONTENT_MSG_READY: break; case CONTENT_MSG_DONE: { const char *source_data; unsigned long source_size; source_data = content_get_source_data(c, &source_size); if (!theme_install_read(source_data, source_size)) warn_user("ThemeInvalid", 0); hlcache_handle_release(c); } break; case CONTENT_MSG_ERROR: warn_user(event->data.error, 0); break; case CONTENT_MSG_STATUS: break; case CONTENT_MSG_LOADING: case CONTENT_MSG_REFORMAT: case CONTENT_MSG_REDRAW: default: assert(0); break; } return NSERROR_OK; }
nserror html_object_abort_objects(html_content *htmlc) { struct content_html_object *object; for (object = htmlc->object_list; object != NULL; object = object->next) { if (object->content == NULL) continue; switch (content_get_status(object->content)) { case CONTENT_STATUS_DONE: /* already loaded: do nothing */ break; case CONTENT_STATUS_READY: hlcache_handle_abort(object->content); /* Active count will be updated when * html_object_callback receives * CONTENT_MSG_DONE from this object */ break; default: hlcache_handle_abort(object->content); hlcache_handle_release(object->content); object->content = NULL; if (object->box != NULL) { htmlc->base.active--; LOG("%d fetches active", htmlc->base.active); } break; } } return NSERROR_OK; }
void html_free_scripts(html_content *html) { unsigned int i; for (i = 0; i != html->scripts_count; i++) { if (html->scripts[i].mimetype != NULL) { dom_string_unref(html->scripts[i].mimetype); } if ((html->scripts[i].type == HTML_SCRIPT_INLINE) && (html->scripts[i].data.string != NULL)) { dom_string_unref(html->scripts[i].data.string); } else if ((html->scripts[i].type == HTML_SCRIPT_SYNC) && (html->scripts[i].data.handle != NULL)) { hlcache_handle_release(html->scripts[i].data.handle); } } free(html->scripts); }
/** * Callback for syncronous scripts */ static nserror convert_script_sync_cb(hlcache_handle *script, const hlcache_event *event, void *pw) { html_content *parent = pw; unsigned int i; struct html_script *s; script_handler_t *script_handler; dom_hubbub_error err; /* Find script */ for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) { if (s->type == HTML_SCRIPT_SYNC && s->data.handle == script) break; } assert(i != parent->scripts_count); switch (event->type) { case CONTENT_MSG_LOADING: break; case CONTENT_MSG_READY: break; case CONTENT_MSG_DONE: LOG(("script %d done '%s'", i, nsurl_access(hlcache_handle_get_url(script)))); parent->base.active--; LOG(("%d fetches active", parent->base.active)); s->already_started = true; /* attempt to execute script */ script_handler = select_script_handler(content_get_type(s->data.handle)); if (script_handler != NULL) { /* script has a handler */ const char *data; unsigned long size; data = content_get_source_data(s->data.handle, &size ); script_handler(parent->jscontext, data, size); } /* continue parse */ err = dom_hubbub_parser_pause(parent->parser, false); if (err != DOM_HUBBUB_OK) { LOG(("unpause returned 0x%x", err)); } break; case CONTENT_MSG_ERROR: LOG(("script %s failed: %s", nsurl_access(hlcache_handle_get_url(script)), event->data.error)); hlcache_handle_release(script); s->data.handle = NULL; parent->base.active--; LOG(("%d fetches active", parent->base.active)); content_add_error(&parent->base, "?", 0); s->already_started = true; /* continue parse */ err = dom_hubbub_parser_pause(parent->parser, false); if (err != DOM_HUBBUB_OK) { LOG(("unpause returned 0x%x", err)); } break; case CONTENT_MSG_STATUS: break; default: assert(0); } /* if there are no active fetches remaining begin post parse * conversion */ if (html_can_begin_conversion(parent)) { html_begin_conversion(parent); } return NSERROR_OK; }
static nserror html_convert_css_callback(hlcache_handle *css, const hlcache_event *event, void *pw) { html_content *parent = pw; unsigned int i; struct html_stylesheet *s; /* Find sheet */ for (i = 0, s = parent->stylesheets; i != parent->stylesheet_count; i++, s++) { if (s->sheet == css) break; } assert(i != parent->stylesheet_count); switch (event->type) { case CONTENT_MSG_LOADING: break; case CONTENT_MSG_READY: break; case CONTENT_MSG_DONE: LOG(("done stylesheet slot %d '%s'", i, nsurl_access(hlcache_handle_get_url(css)))); parent->base.active--; LOG(("%d fetches active", parent->base.active)); break; case CONTENT_MSG_ERROR: LOG(("stylesheet %s failed: %s", nsurl_access(hlcache_handle_get_url(css)), event->data.error)); hlcache_handle_release(css); s->sheet = NULL; parent->base.active--; LOG(("%d fetches active", parent->base.active)); content_add_error(&parent->base, "?", 0); break; case CONTENT_MSG_STATUS: if (event->data.explicit_status_text == NULL) { /* Object content's status text updated */ html_set_status(parent, content_get_status_message(css)); content_broadcast(&parent->base, CONTENT_MSG_STATUS, event->data); } else { /* Object content wants to set explicit message */ content_broadcast(&parent->base, CONTENT_MSG_STATUS, event->data); } break; case CONTENT_MSG_POINTER: /* Really don't want this to continue after the switch */ return NSERROR_OK; default: assert(0); } if (html_can_begin_conversion(parent)) { html_begin_conversion(parent); } return NSERROR_OK; }
nserror favicon_callback(hlcache_handle *icon, const hlcache_event *event, void *pw) { struct content *c = pw; switch (event->type) { case CONTENT_MSG_LOADING: /* check that the favicon is really a correct image type */ if (content_get_type(icon) == CONTENT_UNKNOWN) { union content_msg_data msg_data; LOG(("%s is not a favicon", content_get_url(icon))); hlcache_handle_abort(icon); hlcache_handle_release(icon); c->data.html.favicon = NULL; c->active -= 1; content_add_error(c, "NotFavIco", 0); msg_data.error = messages_get("NotFavIco"); content_broadcast(c, CONTENT_MSG_STATUS, msg_data); } break; case CONTENT_MSG_READY: break; case CONTENT_MSG_DONE: c->active -= 1; break; case CONTENT_MSG_ERROR: LOG(("favicon %s failed: %s", content_get_url(icon), event->data.error)); hlcache_handle_release(c->data.html.favicon); c->data.html.favicon = NULL; content_add_error(c, "?", 0); c->active -= 1; break; case CONTENT_MSG_STATUS: content_broadcast(c, CONTENT_MSG_STATUS, event->data); break; case CONTENT_MSG_REDRAW: /* Fall through */ case CONTENT_MSG_REFRESH: /* Fall through */ case CONTENT_MSG_REFORMAT: break; default: assert(0); } if (c->active == 0) { /* all objects have arrived */ content__reformat(c, c->available_width, c->height); html_set_status(c, ""); content_set_done(c); } return NSERROR_OK; }
static nserror html_object_callback(hlcache_handle *object, const hlcache_event *event, void *pw) { struct content_html_object *o = pw; html_content *c = (html_content *) o->parent; int x, y; struct box *box; assert(c->base.status != CONTENT_STATUS_ERROR); box = o->box; if (box == NULL && event->type != CONTENT_MSG_ERROR) { return NSERROR_OK; } switch (event->type) { case CONTENT_MSG_LOADING: if (c->base.status != CONTENT_STATUS_LOADING && c->bw != NULL) content_open(object, c->bw, &c->base, box->object_params); break; case CONTENT_MSG_READY: if (content_can_reformat(object)) { /* TODO: avoid knowledge of box internals here */ content_reformat(object, false, box->max_width != UNKNOWN_MAX_WIDTH ? box->width : 0, box->max_width != UNKNOWN_MAX_WIDTH ? box->height : 0); /* Adjust parent content for new object size */ html_object_done(box, object, o->background); if (c->base.status == CONTENT_STATUS_READY || c->base.status == CONTENT_STATUS_DONE) content__reformat(&c->base, false, c->base.available_width, c->base.height); } break; case CONTENT_MSG_DONE: c->base.active--; LOG("%d fetches active", c->base.active); html_object_done(box, object, o->background); if (c->base.status != CONTENT_STATUS_LOADING && box->flags & REPLACE_DIM) { union content_msg_data data; if (!box_visible(box)) break; box_coords(box, &x, &y); data.redraw.x = x + box->padding[LEFT]; data.redraw.y = y + box->padding[TOP]; data.redraw.width = box->width; data.redraw.height = box->height; data.redraw.full_redraw = true; content_broadcast(&c->base, CONTENT_MSG_REDRAW, data); } break; case CONTENT_MSG_ERROR: hlcache_handle_release(object); o->content = NULL; if (box != NULL) { c->base.active--; LOG("%d fetches active", c->base.active); content_add_error(&c->base, "?", 0); html_object_failed(box, c, o->background); } break; case CONTENT_MSG_REDRAW: if (c->base.status != CONTENT_STATUS_LOADING) { union content_msg_data data = event->data; if (!box_visible(box)) break; box_coords(box, &x, &y); if (object == box->background) { /* Redraw request is for background */ css_fixed hpos = 0, vpos = 0; css_unit hunit = CSS_UNIT_PX; css_unit vunit = CSS_UNIT_PX; int width = box->padding[LEFT] + box->width + box->padding[RIGHT]; int height = box->padding[TOP] + box->height + box->padding[BOTTOM]; int t, h, l, w; /* Need to know background-position */ css_computed_background_position(box->style, &hpos, &hunit, &vpos, &vunit); w = content_get_width(box->background); if (hunit == CSS_UNIT_PCT) { l = (width - w) * hpos / INTTOFIX(100); } else { l = FIXTOINT(nscss_len2px(hpos, hunit, box->style)); } h = content_get_height(box->background); if (vunit == CSS_UNIT_PCT) { t = (height - h) * vpos / INTTOFIX(100); } else { t = FIXTOINT(nscss_len2px(vpos, vunit, box->style)); } /* Redraw area depends on background-repeat */ switch (css_computed_background_repeat( box->style)) { case CSS_BACKGROUND_REPEAT_REPEAT: data.redraw.x = 0; data.redraw.y = 0; data.redraw.width = box->width; data.redraw.height = box->height; break; case CSS_BACKGROUND_REPEAT_REPEAT_X: data.redraw.x = 0; data.redraw.y += t; data.redraw.width = box->width; break; case CSS_BACKGROUND_REPEAT_REPEAT_Y: data.redraw.x += l; data.redraw.y = 0; data.redraw.height = box->height; break; case CSS_BACKGROUND_REPEAT_NO_REPEAT: data.redraw.x += l; data.redraw.y += t; break; default: break; } data.redraw.object_width = box->width; data.redraw.object_height = box->height; /* Add offset to box */ data.redraw.x += x; data.redraw.y += y; data.redraw.object_x += x; data.redraw.object_y += y; content_broadcast(&c->base, CONTENT_MSG_REDRAW, data); break; } else { /* Non-background case */ if (hlcache_handle_get_content(object) == event->data.redraw.object) { int w = content_get_width(object); int h = content_get_height(object); if (w != 0) { data.redraw.x = data.redraw.x * box->width / w; data.redraw.width = data.redraw.width * box->width / w; } if (h != 0) { data.redraw.y = data.redraw.y * box->height / h; data.redraw.height = data.redraw.height * box->height / h; } data.redraw.object_width = box->width; data.redraw.object_height = box->height; } data.redraw.x += x + box->padding[LEFT]; data.redraw.y += y + box->padding[TOP]; data.redraw.object_x += x + box->padding[LEFT]; data.redraw.object_y += y + box->padding[TOP]; } content_broadcast(&c->base, CONTENT_MSG_REDRAW, data); } break; case CONTENT_MSG_REFRESH: if (content_get_type(object) == CONTENT_HTML) { /* only for HTML objects */ guit->misc->schedule(event->data.delay * 1000, html_object_refresh, o); } break; case CONTENT_MSG_LINK: /* Don't care about favicons that aren't on top level content */ break; case CONTENT_MSG_GETCTX: *(event->data.jscontext) = NULL; break; case CONTENT_MSG_SCROLL: if (box->scroll_x != NULL) scrollbar_set(box->scroll_x, event->data.scroll.x0, false); if (box->scroll_y != NULL) scrollbar_set(box->scroll_y, event->data.scroll.y0, false); break; case CONTENT_MSG_DRAGSAVE: { union content_msg_data msg_data; if (event->data.dragsave.content == NULL) msg_data.dragsave.content = object; else msg_data.dragsave.content = event->data.dragsave.content; content_broadcast(&c->base, CONTENT_MSG_DRAGSAVE, msg_data); } break; case CONTENT_MSG_SAVELINK: case CONTENT_MSG_POINTER: case CONTENT_MSG_SELECTMENU: case CONTENT_MSG_GADGETCLICK: /* These messages are for browser window layer. * we're not interested, so pass them on. */ content_broadcast(&c->base, event->type, event->data); break; case CONTENT_MSG_CARET: { union html_focus_owner focus_owner; focus_owner.content = box; switch (event->data.caret.type) { case CONTENT_CARET_REMOVE: case CONTENT_CARET_HIDE: html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner, true, 0, 0, 0, NULL); break; case CONTENT_CARET_SET_POS: html_set_focus(c, HTML_FOCUS_CONTENT, focus_owner, false, event->data.caret.pos.x, event->data.caret.pos.y, event->data.caret.pos.height, event->data.caret.pos.clip); break; } } break; case CONTENT_MSG_DRAG: { html_drag_type drag_type = HTML_DRAG_NONE; union html_drag_owner drag_owner; drag_owner.content = box; switch (event->data.drag.type) { case CONTENT_DRAG_NONE: drag_type = HTML_DRAG_NONE; drag_owner.no_owner = true; break; case CONTENT_DRAG_SCROLL: drag_type = HTML_DRAG_CONTENT_SCROLL; break; case CONTENT_DRAG_SELECTION: drag_type = HTML_DRAG_CONTENT_SELECTION; break; } html_set_drag_type(c, drag_type, drag_owner, event->data.drag.rect); } break; case CONTENT_MSG_SELECTION: { html_selection_type sel_type; union html_selection_owner sel_owner; if (event->data.selection.selection) { sel_type = HTML_SELECTION_CONTENT; sel_owner.content = box; } else { sel_type = HTML_SELECTION_NONE; sel_owner.none = true; } html_set_selection(c, sel_type, sel_owner, event->data.selection.read_only); } break; default: break; } if (c->base.status == CONTENT_STATUS_READY && c->base.active == 0 && (event->type == CONTENT_MSG_LOADING || event->type == CONTENT_MSG_DONE || event->type == CONTENT_MSG_ERROR)) { /* all objects have arrived */ content__reformat(&c->base, false, c->base.available_width, c->base.height); content_set_done(&c->base); } /* If 1) the configuration option to reflow pages while objects are * fetched is set * 2) an object is newly fetched & converted, * 3) the box's dimensions need to change due to being replaced * 4) the object's parent HTML is ready for reformat, * 5) the time since the previous reformat is more than the * configured minimum time between reformats * then reformat the page to display newly fetched objects */ else if (nsoption_bool(incremental_reflow) && event->type == CONTENT_MSG_DONE && box != NULL && !(box->flags & REPLACE_DIM) && (c->base.status == CONTENT_STATUS_READY || c->base.status == CONTENT_STATUS_DONE) && (wallclock() > c->base.reformat_time)) { content__reformat(&c->base, false, c->base.available_width, c->base.height); } return NSERROR_OK; }
void sslcert_cleanup(void) { if (sslcert_icon != NULL) hlcache_handle_release(sslcert_icon); }
/** * Deletes the global history tree and saves the hotlist. * \param hotlist_path the path where the hotlist should be saved */ void hotlist_cleanup(const char *hotlist_path) { hotlist_export(hotlist_path); hlcache_handle_release(folder_icon); tree_url_node_cleanup(); }