2003-06-25 03:22:00 +04:00
|
|
|
/*
|
2007-01-13 03:21:15 +03:00
|
|
|
* Copyright 2005-2007 James Bursa <bursa@users.sourceforge.net>
|
2007-08-08 20:16:03 +04:00
|
|
|
*
|
|
|
|
* 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
|
2010-03-28 20:00:54 +04:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2007-08-08 20:16:03 +04:00
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
2003-02-09 15:58:15 +03:00
|
|
|
*/
|
|
|
|
|
2003-09-08 01:08:13 +04:00
|
|
|
/** \file
|
|
|
|
* Content handling (implementation).
|
2003-09-11 02:27:15 +04:00
|
|
|
*
|
2003-09-08 01:08:13 +04:00
|
|
|
* This implementation is based on the ::handler_map array, which maps
|
|
|
|
* ::content_type to the functions which implement that type.
|
|
|
|
*/
|
|
|
|
|
2003-02-09 15:58:15 +03:00
|
|
|
#include <assert.h>
|
2005-08-21 16:04:18 +04:00
|
|
|
#include <inttypes.h>
|
2004-06-05 19:03:59 +04:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
2003-02-09 15:58:15 +03:00
|
|
|
#include <stdlib.h>
|
2004-06-05 19:03:59 +04:00
|
|
|
#include <string.h>
|
2007-01-30 01:27:15 +03:00
|
|
|
#include <strings.h>
|
2007-01-13 03:21:15 +03:00
|
|
|
#include <time.h>
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "utils/config.h"
|
2010-03-28 16:56:39 +04:00
|
|
|
#include "content/content_protected.h"
|
|
|
|
#include "content/hlcache.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "css/css.h"
|
|
|
|
#include "image/bitmap.h"
|
2010-06-04 13:35:08 +04:00
|
|
|
#include "desktop/browser.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "desktop/options.h"
|
|
|
|
#include "render/html.h"
|
|
|
|
#include "render/textplain.h"
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_JPEG
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "image/jpeg.h"
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2004-07-16 23:47:03 +04:00
|
|
|
#ifdef WITH_MNG
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "image/mng.h"
|
2004-07-16 23:47:03 +04:00
|
|
|
#endif
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_GIF
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "image/gif.h"
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2006-02-25 21:51:51 +03:00
|
|
|
#ifdef WITH_BMP
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "image/bmp.h"
|
|
|
|
#include "image/ico.h"
|
2006-02-25 21:51:51 +03:00
|
|
|
#endif
|
2007-07-18 18:49:26 +04:00
|
|
|
#ifdef WITH_NS_SVG
|
2007-07-13 07:54:47 +04:00
|
|
|
#include "image/svg.h"
|
2007-07-18 18:49:26 +04:00
|
|
|
#endif
|
2007-07-18 21:58:35 +04:00
|
|
|
#ifdef WITH_RSVG
|
|
|
|
#include "image/rsvg.h"
|
|
|
|
#endif
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_SPRITE
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "riscos/sprite.h"
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2008-03-29 16:30:04 +03:00
|
|
|
#ifdef WITH_NSSPRITE
|
|
|
|
#include "image/nssprite.h"
|
|
|
|
#endif
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_DRAW
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "riscos/draw.h"
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_PLUGIN
|
2011-03-06 16:58:02 +03:00
|
|
|
#include "desktop/plugin.h"
|
2003-07-15 02:57:45 +04:00
|
|
|
#endif
|
2005-12-10 17:31:33 +03:00
|
|
|
#ifdef WITH_ARTWORKS
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "riscos/artworks.h"
|
2005-12-10 17:31:33 +03:00
|
|
|
#endif
|
2008-09-16 00:23:02 +04:00
|
|
|
#ifdef WITH_PNG
|
|
|
|
#include "image/png.h"
|
|
|
|
#endif
|
2010-10-04 00:41:31 +04:00
|
|
|
#ifdef WITH_WEBP
|
|
|
|
#include "image/webp.h"
|
|
|
|
#endif
|
2010-10-30 18:23:38 +04:00
|
|
|
#ifdef WITH_AMIGA_ICON
|
|
|
|
#include "amiga/icon.h"
|
|
|
|
#endif
|
2011-03-05 12:49:15 +03:00
|
|
|
#ifdef WITH_APPLE_IMAGE
|
|
|
|
#include "cocoa/apple_image.h"
|
|
|
|
#endif
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
#include "utils/http.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "utils/log.h"
|
|
|
|
#include "utils/messages.h"
|
|
|
|
#include "utils/talloc.h"
|
|
|
|
#include "utils/utils.h"
|
2003-02-09 15:58:15 +03:00
|
|
|
|
|
|
|
|
2003-09-08 01:08:13 +04:00
|
|
|
/** An entry in mime_map. */
|
2003-02-09 15:58:15 +03:00
|
|
|
struct mime_entry {
|
2003-07-08 02:10:51 +04:00
|
|
|
char mime_type[40];
|
2003-02-09 15:58:15 +03:00
|
|
|
content_type type;
|
|
|
|
};
|
2003-09-08 01:08:13 +04:00
|
|
|
/** A map from MIME type to ::content_type. Must be sorted by mime_type. */
|
2003-02-09 15:58:15 +03:00
|
|
|
static const struct mime_entry mime_map[] = {
|
2006-02-25 21:51:51 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"application/bmp", CONTENT_BMP},
|
|
|
|
#endif
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_DRAW
|
2005-01-14 01:42:39 +03:00
|
|
|
{"application/drawfile", CONTENT_DRAW},
|
2006-02-25 21:51:51 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_BMP
|
2006-02-26 05:25:19 +03:00
|
|
|
{"application/ico", CONTENT_ICO},
|
2006-02-25 21:51:51 +03:00
|
|
|
{"application/preview", CONTENT_BMP},
|
|
|
|
{"application/x-bmp", CONTENT_BMP},
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_DRAW
|
2005-01-14 01:42:39 +03:00
|
|
|
{"application/x-drawfile", CONTENT_DRAW},
|
2005-04-01 06:25:11 +04:00
|
|
|
#endif
|
2006-02-26 05:25:19 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"application/x-ico", CONTENT_ICO},
|
|
|
|
#endif
|
2005-01-14 01:42:39 +03:00
|
|
|
#ifdef WITH_THEME_INSTALL
|
|
|
|
{"application/x-netsurf-theme", CONTENT_THEME},
|
2006-02-25 21:51:51 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"application/x-win-bitmap", CONTENT_BMP},
|
2005-01-14 01:42:39 +03:00
|
|
|
#endif
|
2005-04-01 06:25:11 +04:00
|
|
|
{"application/xhtml+xml", CONTENT_HTML},
|
2006-02-25 21:51:51 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"image/bmp", CONTENT_BMP},
|
|
|
|
#endif
|
2005-04-01 06:25:11 +04:00
|
|
|
#ifdef WITH_DRAW
|
2005-01-14 01:42:39 +03:00
|
|
|
{"image/drawfile", CONTENT_DRAW},
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_GIF
|
2003-06-05 17:17:55 +04:00
|
|
|
{"image/gif", CONTENT_GIF},
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2006-02-26 05:25:19 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"image/ico", CONTENT_ICO},
|
|
|
|
#endif
|
2004-07-17 00:57:14 +04:00
|
|
|
#ifdef WITH_MNG
|
|
|
|
{"image/jng", CONTENT_JNG},
|
|
|
|
#endif
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_JPEG
|
2003-02-26 00:00:27 +03:00
|
|
|
{"image/jpeg", CONTENT_JPEG},
|
2008-09-16 12:13:35 +04:00
|
|
|
{"image/jpg", CONTENT_JPEG},
|
2004-07-26 00:45:16 +04:00
|
|
|
#endif
|
2011-03-05 12:49:15 +03:00
|
|
|
#ifdef WITH_APPLE_IMAGE
|
|
|
|
{"image/jpeg", CONTENT_APPLE_IMAGE},
|
|
|
|
{"image/jpg", CONTENT_APPLE_IMAGE},
|
|
|
|
#endif
|
2004-07-26 00:45:16 +04:00
|
|
|
#ifdef WITH_MNG
|
|
|
|
{"image/mng", CONTENT_MNG},
|
|
|
|
#endif
|
2006-02-25 21:51:51 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"image/ms-bmp", CONTENT_BMP},
|
|
|
|
#endif
|
2004-07-26 00:45:16 +04:00
|
|
|
#ifdef WITH_JPEG
|
2004-03-16 03:51:34 +03:00
|
|
|
{"image/pjpeg", CONTENT_JPEG},
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2011-03-05 12:49:15 +03:00
|
|
|
#ifdef WITH_APPLE_IMAGE
|
|
|
|
{"image/pjpeg", CONTENT_APPLE_IMAGE},
|
|
|
|
#endif
|
2008-09-16 00:23:02 +04:00
|
|
|
#if defined(WITH_MNG) || defined(WITH_PNG)
|
2003-05-10 15:15:49 +04:00
|
|
|
{"image/png", CONTENT_PNG},
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2007-07-18 21:58:35 +04:00
|
|
|
#if defined(WITH_NS_SVG) || defined (WITH_RSVG)
|
2007-07-13 07:54:47 +04:00
|
|
|
{"image/svg", CONTENT_SVG},
|
|
|
|
{"image/svg+xml", CONTENT_SVG},
|
2007-07-18 18:49:26 +04:00
|
|
|
#endif
|
2009-12-18 02:55:02 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"image/vnd.microsoft.icon", CONTENT_ICO},
|
|
|
|
#endif
|
2010-10-04 00:41:31 +04:00
|
|
|
#ifdef WITH_WEBP
|
|
|
|
{"image/webp", CONTENT_WEBP},
|
|
|
|
#endif
|
2010-10-30 18:23:38 +04:00
|
|
|
#ifdef WITH_AMIGA_ICON
|
|
|
|
{"image/x-amiga-icon", CONTENT_AMIGA_ICON},
|
|
|
|
#endif
|
2007-07-21 04:20:04 +04:00
|
|
|
#ifdef WITH_ARTWORKS
|
|
|
|
{"image/x-artworks", CONTENT_ARTWORKS},
|
|
|
|
#endif
|
2006-02-25 21:51:51 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"image/x-bitmap", CONTENT_BMP},
|
|
|
|
{"image/x-bmp", CONTENT_BMP},
|
|
|
|
#endif
|
2004-07-17 00:57:14 +04:00
|
|
|
#ifdef WITH_DRAW
|
|
|
|
{"image/x-drawfile", CONTENT_DRAW},
|
|
|
|
#endif
|
2006-02-26 05:25:19 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"image/x-icon", CONTENT_ICO},
|
|
|
|
#endif
|
2004-07-16 23:47:03 +04:00
|
|
|
#ifdef WITH_MNG
|
|
|
|
{"image/x-jng", CONTENT_JNG},
|
|
|
|
{"image/x-mng", CONTENT_MNG},
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2006-02-25 21:51:51 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"image/x-ms-bmp", CONTENT_BMP},
|
|
|
|
#endif
|
2008-03-29 16:30:04 +03:00
|
|
|
#if defined(WITH_SPRITE) || defined(WITH_NSSPRITE)
|
2003-09-11 02:27:15 +04:00
|
|
|
{"image/x-riscos-sprite", CONTENT_SPRITE},
|
2006-02-25 21:51:51 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_BMP
|
|
|
|
{"image/x-win-bitmap", CONTENT_BMP},
|
|
|
|
{"image/x-windows-bmp", CONTENT_BMP},
|
|
|
|
{"image/x-xbitmap", CONTENT_BMP},
|
2003-06-17 23:24:21 +04:00
|
|
|
#endif
|
2003-04-04 19:19:32 +04:00
|
|
|
{"text/css", CONTENT_CSS},
|
2003-02-09 15:58:15 +03:00
|
|
|
{"text/html", CONTENT_HTML},
|
|
|
|
{"text/plain", CONTENT_TEXTPLAIN},
|
2004-07-17 00:57:14 +04:00
|
|
|
#ifdef WITH_MNG
|
|
|
|
{"video/mng", CONTENT_MNG},
|
|
|
|
{"video/x-mng", CONTENT_MNG},
|
|
|
|
#endif
|
2003-02-09 15:58:15 +03:00
|
|
|
};
|
|
|
|
#define MIME_MAP_COUNT (sizeof(mime_map) / sizeof(mime_map[0]))
|
|
|
|
|
2008-07-30 04:54:43 +04:00
|
|
|
const char * const content_type_name[] = {
|
2004-06-11 00:41:26 +04:00
|
|
|
"HTML",
|
|
|
|
"TEXTPLAIN",
|
|
|
|
"CSS",
|
|
|
|
#ifdef WITH_JPEG
|
|
|
|
"JPEG",
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_GIF
|
|
|
|
"GIF",
|
|
|
|
#endif
|
2006-02-25 21:51:51 +03:00
|
|
|
#ifdef WITH_BMP
|
|
|
|
"BMP",
|
2006-02-26 05:25:19 +03:00
|
|
|
"ICO",
|
2006-02-25 21:51:51 +03:00
|
|
|
#endif
|
2008-09-16 00:23:02 +04:00
|
|
|
#if defined(WITH_MNG) || defined(WITH_PNG)
|
2004-09-04 02:44:48 +04:00
|
|
|
"PNG",
|
2008-09-16 00:23:02 +04:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_MNG
|
2004-07-17 00:02:28 +04:00
|
|
|
"JNG",
|
2004-07-16 23:47:03 +04:00
|
|
|
"MNG",
|
|
|
|
#endif
|
2008-03-29 16:30:04 +03:00
|
|
|
#if defined(WITH_SPRITE) || defined(WITH_NSSPRITE)
|
2004-06-11 00:41:26 +04:00
|
|
|
"SPRITE",
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_DRAW
|
|
|
|
"DRAW",
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_PLUGIN
|
|
|
|
"PLUGIN",
|
2005-01-14 01:42:39 +03:00
|
|
|
#endif
|
2006-07-06 04:07:11 +04:00
|
|
|
"DIRECTORY",
|
2005-01-14 01:42:39 +03:00
|
|
|
#ifdef WITH_THEME_INSTALL
|
|
|
|
"THEME",
|
2005-12-10 17:31:33 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_ARTWORKS
|
|
|
|
"ARTWORKS",
|
2007-07-21 04:14:15 +04:00
|
|
|
#endif
|
|
|
|
#if defined(WITH_NS_SVG) || defined(WITH_RSVG)
|
|
|
|
"SVG",
|
2010-10-04 00:41:31 +04:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_WEBP
|
|
|
|
"WEBP",
|
2010-10-30 18:23:38 +04:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_AMIGA_ICON
|
|
|
|
"AMIGA_ICON",
|
2011-03-05 12:49:15 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_APPLE_IMAGE
|
|
|
|
"APPLE_IMAGE",
|
2004-06-11 00:41:26 +04:00
|
|
|
#endif
|
|
|
|
"OTHER",
|
|
|
|
"UNKNOWN"
|
|
|
|
};
|
|
|
|
|
2008-07-30 04:54:43 +04:00
|
|
|
const char * const content_status_name[] = {
|
2004-06-11 00:41:26 +04:00
|
|
|
"LOADING",
|
|
|
|
"READY",
|
|
|
|
"DONE",
|
|
|
|
"ERROR"
|
|
|
|
};
|
|
|
|
|
2003-09-08 01:08:13 +04:00
|
|
|
/** An entry in handler_map. */
|
2003-02-09 15:58:15 +03:00
|
|
|
struct handler_entry {
|
2010-03-28 16:56:39 +04:00
|
|
|
bool (*create)(struct content *c, const http_parameter *params);
|
2010-04-03 20:37:36 +04:00
|
|
|
bool (*process_data)(struct content *c,
|
|
|
|
const char *data, unsigned int size);
|
2010-03-30 02:33:21 +04:00
|
|
|
bool (*convert)(struct content *c);
|
2004-06-11 00:41:26 +04:00
|
|
|
void (*reformat)(struct content *c, int width, int height);
|
2003-02-09 15:58:15 +03:00
|
|
|
void (*destroy)(struct content *c);
|
2004-06-21 03:09:52 +04:00
|
|
|
void (*stop)(struct content *c);
|
2010-06-04 13:35:08 +04:00
|
|
|
void (*mouse_track)(struct content *c, struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y);
|
|
|
|
void (*mouse_action)(struct content *c, struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y);
|
2004-08-11 20:26:13 +04:00
|
|
|
bool (*redraw)(struct content *c, int x, int y,
|
2011-02-14 22:17:08 +03:00
|
|
|
int width, int height, const struct rect *clip,
|
2008-09-29 02:37:13 +04:00
|
|
|
float scale, colour background_colour);
|
2006-02-21 23:49:12 +03:00
|
|
|
bool (*redraw_tiled)(struct content *c, int x, int y,
|
2011-02-14 22:17:08 +03:00
|
|
|
int width, int height, const struct rect *clip,
|
2008-09-29 02:37:13 +04:00
|
|
|
float scale, colour background_colour,
|
2006-02-21 23:49:12 +03:00
|
|
|
bool repeat_x, bool repeat_y);
|
2004-08-12 02:08:26 +04:00
|
|
|
void (*open)(struct content *c, struct browser_window *bw,
|
2005-10-31 00:22:19 +03:00
|
|
|
struct content *page, unsigned int index,
|
|
|
|
struct box *box,
|
2004-08-12 02:08:26 +04:00
|
|
|
struct object_params *params);
|
|
|
|
void (*close)(struct content *c);
|
2010-04-04 16:41:19 +04:00
|
|
|
bool (*clone)(const struct content *old, struct content *new_content);
|
2004-08-11 23:02:32 +04:00
|
|
|
/** There must be one content per user for this type. */
|
|
|
|
bool no_share;
|
2003-02-09 15:58:15 +03:00
|
|
|
};
|
2003-09-08 01:08:13 +04:00
|
|
|
/** A table of handler functions, indexed by ::content_type.
|
|
|
|
* Must be ordered as enum ::content_type. */
|
2003-02-09 15:58:15 +03:00
|
|
|
static const struct handler_entry handler_map[] = {
|
2004-06-11 00:41:26 +04:00
|
|
|
{html_create, html_process_data, html_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
html_reformat, html_destroy, html_stop, html_mouse_track,
|
|
|
|
html_mouse_action, html_redraw, 0, html_open, html_close,
|
|
|
|
html_clone, true},
|
2004-11-22 03:33:04 +03:00
|
|
|
{textplain_create, textplain_process_data, textplain_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
textplain_reformat, textplain_destroy, 0, textplain_mouse_track,
|
|
|
|
textplain_mouse_action, textplain_redraw, 0, 0, 0,
|
|
|
|
textplain_clone, true},
|
2009-07-24 03:05:34 +04:00
|
|
|
{nscss_create, nscss_process_data, nscss_convert, 0, nscss_destroy,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, 0, 0, 0, 0, 0, 0, nscss_clone, false},
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_JPEG
|
2010-06-04 13:35:08 +04:00
|
|
|
{0, 0, nsjpeg_convert, 0, nsjpeg_destroy, 0, 0, 0,
|
2010-04-04 16:41:19 +04:00
|
|
|
nsjpeg_redraw, nsjpeg_redraw_tiled, 0, 0, nsjpeg_clone, false},
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2004-04-25 03:42:32 +04:00
|
|
|
#ifdef WITH_GIF
|
2010-06-04 13:35:08 +04:00
|
|
|
{nsgif_create, 0, nsgif_convert, 0, nsgif_destroy, 0, 0, 0,
|
2010-04-04 16:41:19 +04:00
|
|
|
nsgif_redraw, nsgif_redraw_tiled, 0, 0, nsgif_clone, false},
|
2004-04-25 03:42:32 +04:00
|
|
|
#endif
|
2006-02-25 21:51:51 +03:00
|
|
|
#ifdef WITH_BMP
|
2010-06-04 13:35:08 +04:00
|
|
|
{nsbmp_create, 0, nsbmp_convert, 0, nsbmp_destroy, 0, 0, 0,
|
2010-04-04 16:41:19 +04:00
|
|
|
nsbmp_redraw, nsbmp_redraw_tiled, 0, 0, nsbmp_clone, false},
|
2010-06-04 13:35:08 +04:00
|
|
|
{nsico_create, 0, nsico_convert, 0, nsico_destroy, 0, 0, 0,
|
2010-04-04 16:41:19 +04:00
|
|
|
nsico_redraw, nsico_redraw_tiled, 0, 0, nsico_clone, false},
|
2006-02-25 21:51:51 +03:00
|
|
|
#endif
|
2008-09-16 00:23:02 +04:00
|
|
|
|
|
|
|
#ifdef WITH_PNG
|
|
|
|
{nspng_create, nspng_process_data, nspng_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, nspng_destroy, 0, 0, 0, nspng_redraw, nspng_redraw_tiled,
|
2010-04-04 16:41:19 +04:00
|
|
|
0, 0, nspng_clone, false},
|
2008-09-16 00:23:02 +04:00
|
|
|
#else
|
2004-09-04 02:44:48 +04:00
|
|
|
#ifdef WITH_MNG
|
2004-07-26 00:45:16 +04:00
|
|
|
{nsmng_create, nsmng_process_data, nsmng_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, nsmng_destroy, 0, 0, 0, nsmng_redraw, nsmng_redraw_tiled,
|
2010-04-04 16:41:19 +04:00
|
|
|
0, 0, nsmng_clone, false},
|
2008-09-16 00:23:02 +04:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_MNG
|
2004-07-16 23:47:03 +04:00
|
|
|
{nsmng_create, nsmng_process_data, nsmng_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, nsmng_destroy, 0, 0, 0, nsmng_redraw, nsmng_redraw_tiled,
|
2010-04-04 16:41:19 +04:00
|
|
|
0, 0, nsmng_clone, false},
|
2004-07-17 00:02:28 +04:00
|
|
|
{nsmng_create, nsmng_process_data, nsmng_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, nsmng_destroy, 0, 0, 0, nsmng_redraw, nsmng_redraw_tiled,
|
2010-04-04 16:41:19 +04:00
|
|
|
0, 0, nsmng_clone, false},
|
2004-07-16 23:47:03 +04:00
|
|
|
#endif
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_SPRITE
|
2005-04-05 21:19:58 +04:00
|
|
|
{0, 0, sprite_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, sprite_destroy, 0, 0, 0, sprite_redraw, 0,
|
2010-04-04 16:41:19 +04:00
|
|
|
0, 0, sprite_clone, false},
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2008-03-29 16:30:04 +03:00
|
|
|
#ifdef WITH_NSSPRITE
|
|
|
|
{0, 0, nssprite_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, nssprite_destroy, 0, 0, 0, nssprite_redraw, 0,
|
2010-04-04 16:41:19 +04:00
|
|
|
0, 0, nssprite_clone, false},
|
2008-03-29 16:30:04 +03:00
|
|
|
#endif
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_DRAW
|
2004-06-11 00:41:26 +04:00
|
|
|
{0, 0, draw_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, draw_destroy, 0, 0, 0, draw_redraw, 0, 0, 0, draw_clone,
|
|
|
|
false},
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_PLUGIN
|
2004-08-11 20:26:13 +04:00
|
|
|
{plugin_create, 0, plugin_convert,
|
2011-03-06 16:58:02 +03:00
|
|
|
plugin_reformat, plugin_destroy, 0, 0, 0, plugin_redraw, 0,
|
2010-04-04 16:41:19 +04:00
|
|
|
plugin_open, plugin_close, plugin_clone,
|
2004-08-12 02:08:26 +04:00
|
|
|
true},
|
2005-01-14 01:42:39 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_THEME_INSTALL
|
2010-06-04 13:35:08 +04:00
|
|
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false},
|
2005-12-10 17:31:33 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_ARTWORKS
|
|
|
|
{0, 0, artworks_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, artworks_destroy, 0, 0, 0, artworks_redraw, 0,
|
2010-04-04 16:41:19 +04:00
|
|
|
0, 0, artworks_clone, false},
|
2003-06-17 23:24:21 +04:00
|
|
|
#endif
|
2007-07-18 18:49:26 +04:00
|
|
|
#ifdef WITH_NS_SVG
|
2007-07-13 07:54:47 +04:00
|
|
|
{svg_create, 0, svg_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
svg_reformat, svg_destroy, 0, 0, 0, svg_redraw, 0,
|
2010-04-04 16:41:19 +04:00
|
|
|
0, 0, svg_clone, true},
|
2007-07-18 21:58:35 +04:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_RSVG
|
2007-07-19 17:47:59 +04:00
|
|
|
{rsvg_create, rsvg_process_data, rsvg_convert,
|
2010-06-04 13:35:08 +04:00
|
|
|
0, rsvg_destroy, 0, 0, 0, rsvg_redraw, 0, 0, 0, rsvg_clone,
|
|
|
|
false},
|
2010-10-04 00:41:31 +04:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_WEBP
|
|
|
|
{0, 0, webp_convert,
|
|
|
|
0, webp_destroy, 0, 0, 0, webp_redraw, 0,
|
|
|
|
0, 0, webp_clone, false},
|
2010-10-30 18:23:38 +04:00
|
|
|
#endif
|
2010-10-31 16:27:31 +03:00
|
|
|
#ifdef WITH_AMIGA_ICON
|
2010-10-30 18:23:38 +04:00
|
|
|
{0, 0, amiga_icon_convert,
|
|
|
|
0, amiga_icon_destroy, 0, 0, 0, amiga_icon_redraw, 0,
|
|
|
|
0, 0, amiga_icon_clone, false},
|
2011-03-05 12:49:15 +03:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_APPLE_IMAGE
|
|
|
|
{0, 0, apple_image_convert, 0, apple_image_destroy, 0, 0, 0,
|
|
|
|
apple_image_redraw, apple_image_redraw_tiled, 0, 0, apple_image_clone, false},
|
2007-07-18 18:49:26 +04:00
|
|
|
#endif
|
2010-06-04 13:35:08 +04:00
|
|
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false}
|
2003-02-09 15:58:15 +03:00
|
|
|
};
|
2003-06-17 23:24:21 +04:00
|
|
|
#define HANDLER_MAP_COUNT (sizeof(handler_map) / sizeof(handler_map[0]))
|
2003-02-09 15:58:15 +03:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
static nserror content_llcache_callback(llcache_handle *llcache,
|
|
|
|
const llcache_event *event, void *pw);
|
2010-03-30 02:33:21 +04:00
|
|
|
static void content_convert(struct content *c);
|
2007-01-13 03:21:15 +03:00
|
|
|
static void content_update_status(struct content *c);
|
2004-06-21 03:09:52 +04:00
|
|
|
|
|
|
|
|
2003-02-09 15:58:15 +03:00
|
|
|
/**
|
2003-09-08 01:08:13 +04:00
|
|
|
* Convert a MIME type to a content_type.
|
|
|
|
*
|
2010-03-28 16:56:39 +04:00
|
|
|
* The returned ::content_type will always be suitable for content_create().
|
2003-02-09 15:58:15 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
content_type content_lookup(const char *mime_type)
|
|
|
|
{
|
|
|
|
struct mime_entry *m;
|
|
|
|
m = bsearch(mime_type, mime_map, MIME_MAP_COUNT, sizeof(mime_map[0]),
|
2004-04-20 22:27:46 +04:00
|
|
|
(int (*)(const void *, const void *)) strcasecmp);
|
2003-07-10 01:33:01 +04:00
|
|
|
if (m == 0) {
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_PLUGIN
|
2003-07-10 01:33:01 +04:00
|
|
|
if (plugin_handleable(mime_type))
|
|
|
|
return CONTENT_PLUGIN;
|
2003-07-15 02:57:45 +04:00
|
|
|
#endif
|
2003-02-09 15:58:15 +03:00
|
|
|
return CONTENT_OTHER;
|
2003-07-10 01:33:01 +04:00
|
|
|
}
|
2003-02-09 15:58:15 +03:00
|
|
|
return m->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2003-09-08 01:08:13 +04:00
|
|
|
* Create a new content structure.
|
|
|
|
*
|
2010-03-28 20:00:54 +04:00
|
|
|
* \param url URL of content, copied
|
2004-06-11 00:41:26 +04:00
|
|
|
* \return the new content structure, or 0 on memory exhaustion
|
2003-02-09 15:58:15 +03:00
|
|
|
*/
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
struct content * content_create(llcache_handle *llcache,
|
|
|
|
const char *fallback_charset, bool quirks)
|
2003-02-09 15:58:15 +03:00
|
|
|
{
|
|
|
|
struct content *c;
|
2003-06-17 23:24:21 +04:00
|
|
|
struct content_user *user_sentinel;
|
2010-03-28 16:56:39 +04:00
|
|
|
const char *content_type_header;
|
|
|
|
content_type type;
|
|
|
|
char *mime_type;
|
|
|
|
http_parameter *params;
|
|
|
|
nserror error;
|
|
|
|
|
|
|
|
content_type_header =
|
|
|
|
llcache_handle_get_header(llcache, "Content-Type");
|
|
|
|
if (content_type_header == NULL)
|
|
|
|
content_type_header = "text/plain";
|
|
|
|
|
|
|
|
error = http_parse_content_type(content_type_header, &mime_type,
|
|
|
|
¶ms);
|
|
|
|
if (error != NSERROR_OK)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
type = content_lookup(mime_type);
|
2007-03-18 20:04:18 +03:00
|
|
|
|
2007-03-18 23:19:13 +03:00
|
|
|
c = talloc_zero(0, struct content);
|
2010-03-28 16:56:39 +04:00
|
|
|
if (c == NULL) {
|
|
|
|
http_parameter_list_destroy(params);
|
|
|
|
free(mime_type);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-03-18 20:04:18 +03:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
LOG(("url %s -> %p", llcache_handle_get_url(llcache), c));
|
2007-03-18 20:04:18 +03:00
|
|
|
|
2005-04-03 14:58:49 +04:00
|
|
|
user_sentinel = talloc(c, struct content_user);
|
2010-03-28 16:56:39 +04:00
|
|
|
if (user_sentinel == NULL) {
|
2005-04-03 14:58:49 +04:00
|
|
|
talloc_free(c);
|
2010-03-28 16:56:39 +04:00
|
|
|
http_parameter_list_destroy(params);
|
|
|
|
free(mime_type);
|
|
|
|
return NULL;
|
2004-06-11 00:41:26 +04:00
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
c->fallback_charset = talloc_strdup(c, fallback_charset);
|
|
|
|
if (fallback_charset != NULL && c->fallback_charset == NULL) {
|
2005-04-03 14:58:49 +04:00
|
|
|
talloc_free(c);
|
2010-03-28 16:56:39 +04:00
|
|
|
http_parameter_list_destroy(params);
|
|
|
|
free(mime_type);
|
|
|
|
return NULL;
|
2004-06-11 00:41:26 +04:00
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
c->mime_type = talloc_strdup(c, mime_type);
|
|
|
|
if (c->mime_type == NULL) {
|
|
|
|
talloc_free(c);
|
|
|
|
http_parameter_list_destroy(params);
|
|
|
|
free(mime_type);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No longer require mime_type */
|
|
|
|
free(mime_type);
|
|
|
|
|
|
|
|
c->llcache = llcache;
|
|
|
|
c->type = type;
|
|
|
|
c->status = CONTENT_STATUS_LOADING;
|
2004-06-11 00:41:26 +04:00
|
|
|
c->width = 0;
|
|
|
|
c->height = 0;
|
|
|
|
c->available_width = 0;
|
2010-03-28 16:56:39 +04:00
|
|
|
c->quirks = quirks;
|
2006-01-25 09:52:38 +03:00
|
|
|
c->refresh = 0;
|
2010-03-28 16:56:39 +04:00
|
|
|
c->bitmap = NULL;
|
2007-01-30 18:32:31 +03:00
|
|
|
c->time = wallclock();
|
2006-12-04 01:34:26 +03:00
|
|
|
c->size = 0;
|
2010-03-28 16:56:39 +04:00
|
|
|
c->title = NULL;
|
2004-06-11 00:41:26 +04:00
|
|
|
c->active = 0;
|
2010-03-28 16:56:39 +04:00
|
|
|
user_sentinel->callback = NULL;
|
|
|
|
user_sentinel->pw = NULL;
|
|
|
|
user_sentinel->next = NULL;
|
2003-06-17 23:24:21 +04:00
|
|
|
c->user_list = user_sentinel;
|
2007-01-13 03:21:15 +03:00
|
|
|
c->sub_status[0] = 0;
|
2005-07-06 02:43:38 +04:00
|
|
|
c->locked = false;
|
2004-06-11 00:41:26 +04:00
|
|
|
c->total_size = 0;
|
2007-01-13 03:21:15 +03:00
|
|
|
c->http_code = 0;
|
2004-06-11 00:41:26 +04:00
|
|
|
c->error_count = 0;
|
|
|
|
|
2007-01-13 03:21:15 +03:00
|
|
|
content_set_status(c, messages_get("Loading"));
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
if (handler_map[type].create) {
|
|
|
|
if (handler_map[type].create(c, params) == false) {
|
|
|
|
talloc_free(c);
|
|
|
|
http_parameter_list_destroy(params);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2004-06-21 19:09:59 +04:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
http_parameter_list_destroy(params);
|
2004-06-21 19:09:59 +04:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
/* Finally, claim low-level cache events */
|
|
|
|
if (llcache_handle_change_callback(llcache,
|
|
|
|
content_llcache_callback, c) != NSERROR_OK) {
|
|
|
|
talloc_free(c);
|
|
|
|
return NULL;
|
2004-06-21 19:09:59 +04:00
|
|
|
}
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
return c;
|
2004-06-21 19:09:59 +04:00
|
|
|
}
|
|
|
|
|
2006-02-06 03:10:09 +03:00
|
|
|
/**
|
2010-03-28 16:56:39 +04:00
|
|
|
* Handler for low-level cache events
|
2006-02-06 03:10:09 +03:00
|
|
|
*
|
2010-03-28 16:56:39 +04:00
|
|
|
* \param llcache Low-level cache handle
|
2010-03-28 20:00:54 +04:00
|
|
|
* \param event Event details
|
|
|
|
* \param pw Pointer to our context
|
2010-03-28 16:56:39 +04:00
|
|
|
* \return NSERROR_OK on success, appropriate error otherwise
|
2006-02-06 03:10:09 +03:00
|
|
|
*/
|
2010-03-28 16:56:39 +04:00
|
|
|
nserror content_llcache_callback(llcache_handle *llcache,
|
|
|
|
const llcache_event *event, void *pw)
|
2006-02-06 03:10:09 +03:00
|
|
|
{
|
2010-03-28 16:56:39 +04:00
|
|
|
struct content *c = pw;
|
|
|
|
union content_msg_data msg_data;
|
|
|
|
nserror error = NSERROR_OK;
|
|
|
|
|
|
|
|
switch (event->type) {
|
|
|
|
case LLCACHE_EVENT_HAD_HEADERS:
|
|
|
|
/* Will never happen: handled in hlcache */
|
|
|
|
break;
|
|
|
|
case LLCACHE_EVENT_HAD_DATA:
|
|
|
|
if (handler_map[c->type].process_data) {
|
|
|
|
if (handler_map[c->type].process_data(c,
|
2010-04-03 20:37:36 +04:00
|
|
|
(const char *) event->data.data.buf,
|
2010-03-28 16:56:39 +04:00
|
|
|
event->data.data.len) == false) {
|
2010-04-08 11:09:09 +04:00
|
|
|
llcache_handle_abort(c->llcache);
|
2010-03-28 16:56:39 +04:00
|
|
|
c->status = CONTENT_STATUS_ERROR;
|
|
|
|
/** \todo It's not clear what error this is */
|
|
|
|
error = NSERROR_NOMEM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LLCACHE_EVENT_DONE:
|
|
|
|
{
|
|
|
|
const uint8_t *source;
|
|
|
|
size_t source_size;
|
|
|
|
|
|
|
|
source = llcache_handle_get_source_data(llcache, &source_size);
|
2006-02-06 03:10:09 +03:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
content_set_status(c, messages_get("Converting"), source_size);
|
|
|
|
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
|
|
|
|
|
2010-03-30 02:33:21 +04:00
|
|
|
content_convert(c);
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LLCACHE_EVENT_ERROR:
|
|
|
|
/** \todo Error page? */
|
|
|
|
c->status = CONTENT_STATUS_ERROR;
|
|
|
|
msg_data.error = event->data.msg;
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
break;
|
|
|
|
case LLCACHE_EVENT_PROGRESS:
|
|
|
|
content_set_status(c, "%s", event->data.msg);
|
|
|
|
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
|
|
|
|
break;
|
2006-02-06 03:10:09 +03:00
|
|
|
}
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
return error;
|
2006-02-06 03:10:09 +03:00
|
|
|
}
|
|
|
|
|
2007-03-03 22:46:20 +03:00
|
|
|
/**
|
|
|
|
* Get whether a content can reformat
|
|
|
|
*
|
2010-03-28 16:56:39 +04:00
|
|
|
* \param h content to check
|
2007-03-03 22:46:20 +03:00
|
|
|
* \return whether the content can reformat
|
|
|
|
*/
|
2010-03-28 16:56:39 +04:00
|
|
|
bool content_can_reformat(hlcache_handle *h)
|
2007-08-07 07:55:18 +04:00
|
|
|
{
|
2010-03-28 16:56:39 +04:00
|
|
|
struct content *c = hlcache_handle_get_content(h);
|
2007-03-03 22:46:20 +03:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
if (c == NULL)
|
2004-06-11 00:41:26 +04:00
|
|
|
return false;
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
return (handler_map[c->type].reformat != NULL);
|
2003-06-17 23:24:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-05 19:03:59 +04:00
|
|
|
/**
|
|
|
|
* Updates content with new status.
|
|
|
|
*
|
|
|
|
* The textual status contained in the content is updated with given string.
|
|
|
|
*
|
|
|
|
* \param status_message new textual status
|
|
|
|
*/
|
2004-06-21 19:09:59 +04:00
|
|
|
|
2004-06-05 19:03:59 +04:00
|
|
|
void content_set_status(struct content *c, const char *status_message, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
va_start(ap, status_message);
|
2007-01-13 03:21:15 +03:00
|
|
|
if ((len = vsnprintf(c->sub_status, sizeof (c->sub_status),
|
2005-07-06 02:43:38 +04:00
|
|
|
status_message, ap)) < 0 ||
|
2007-01-13 03:21:15 +03:00
|
|
|
(int)sizeof (c->sub_status) <= len)
|
|
|
|
c->sub_status[sizeof (c->sub_status) - 1] = '\0';
|
2004-06-05 19:03:59 +04:00
|
|
|
va_end(ap);
|
2007-01-13 03:21:15 +03:00
|
|
|
|
|
|
|
content_update_status(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void content_update_status(struct content *c)
|
|
|
|
{
|
|
|
|
char token[20];
|
|
|
|
const char *status;
|
2007-01-30 18:32:31 +03:00
|
|
|
unsigned int time;
|
2007-01-13 03:21:15 +03:00
|
|
|
|
|
|
|
snprintf(token, sizeof token, "HTTP%li", c->http_code);
|
|
|
|
status = messages_get(token);
|
|
|
|
if (status == token)
|
|
|
|
status = token + 4;
|
|
|
|
|
2011-02-28 23:38:23 +03:00
|
|
|
if (c->status == CONTENT_STATUS_LOADING ||
|
2007-01-13 03:21:15 +03:00
|
|
|
c->status == CONTENT_STATUS_READY)
|
2007-01-30 18:32:31 +03:00
|
|
|
time = wallclock() - c->time;
|
2007-01-13 03:21:15 +03:00
|
|
|
else
|
|
|
|
time = c->time;
|
|
|
|
|
|
|
|
snprintf(c->status_message, sizeof (c->status_message),
|
|
|
|
"%s (%.1fs) %s", status,
|
2007-01-30 18:32:31 +03:00
|
|
|
(float) time / 100, c->sub_status);
|
2007-01-13 03:21:15 +03:00
|
|
|
/* LOG(("%s", c->status_message)); */
|
2004-06-05 19:03:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-09 15:58:15 +03:00
|
|
|
/**
|
2003-09-08 01:08:13 +04:00
|
|
|
* All data has arrived, convert for display.
|
|
|
|
*
|
|
|
|
* Calls the convert function for the content.
|
|
|
|
*
|
|
|
|
* - If the conversion succeeds, but there is still some processing required
|
|
|
|
* (eg. loading images), the content gets status CONTENT_STATUS_READY, and a
|
|
|
|
* CONTENT_MSG_READY is sent to all users.
|
|
|
|
* - If the conversion succeeds and is complete, the content gets status
|
2004-02-25 18:12:58 +03:00
|
|
|
* CONTENT_STATUS_DONE, and CONTENT_MSG_READY then CONTENT_MSG_DONE are sent.
|
2004-06-11 00:41:26 +04:00
|
|
|
* - If the conversion fails, CONTENT_MSG_ERROR is sent. The content will soon
|
|
|
|
* be destroyed and must no longer be used.
|
2003-02-09 15:58:15 +03:00
|
|
|
*/
|
|
|
|
|
2010-03-30 02:33:21 +04:00
|
|
|
void content_convert(struct content *c)
|
2003-02-09 15:58:15 +03:00
|
|
|
{
|
2004-06-11 00:41:26 +04:00
|
|
|
assert(c);
|
2003-06-17 23:24:21 +04:00
|
|
|
assert(c->type < HANDLER_MAP_COUNT);
|
2010-04-18 15:04:13 +04:00
|
|
|
assert(c->status == CONTENT_STATUS_LOADING ||
|
|
|
|
c->status == CONTENT_STATUS_ERROR);
|
|
|
|
|
|
|
|
if (c->status != CONTENT_STATUS_LOADING)
|
|
|
|
return;
|
|
|
|
|
2010-03-28 20:00:54 +04:00
|
|
|
if (c->locked == true)
|
|
|
|
return;
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
LOG(("content %s (%p)", llcache_handle_get_url(c->llcache), c));
|
2005-04-05 06:36:33 +04:00
|
|
|
|
2004-03-11 05:19:14 +03:00
|
|
|
if (handler_map[c->type].convert) {
|
2011-02-27 23:11:39 +03:00
|
|
|
c->locked = true;
|
2011-02-28 22:58:08 +03:00
|
|
|
if (handler_map[c->type].convert(c) == false) {
|
|
|
|
c->locked = false;
|
2004-06-11 00:41:26 +04:00
|
|
|
c->status = CONTENT_STATUS_ERROR;
|
2004-03-11 05:19:14 +03:00
|
|
|
}
|
2011-02-28 22:58:08 +03:00
|
|
|
/* Conversion to the READY state will unlock the content */
|
2004-03-11 05:19:14 +03:00
|
|
|
} else {
|
2010-04-11 14:52:18 +04:00
|
|
|
content_set_ready(c);
|
2007-01-13 03:21:15 +03:00
|
|
|
content_set_done(c);
|
2010-04-11 14:52:18 +04:00
|
|
|
}
|
2007-01-13 03:21:15 +03:00
|
|
|
}
|
|
|
|
|
2010-04-09 22:52:44 +04:00
|
|
|
/**
|
2011-02-28 22:58:08 +03:00
|
|
|
* Put a content in status CONTENT_STATUS_READY and unlock the content.
|
2010-04-09 22:52:44 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
void content_set_ready(struct content *c)
|
|
|
|
{
|
|
|
|
union content_msg_data msg_data;
|
|
|
|
|
2011-02-28 22:58:08 +03:00
|
|
|
/* The content must be locked at this point, as it can only
|
|
|
|
* become READY after conversion. */
|
|
|
|
assert(c->locked);
|
|
|
|
c->locked = false;
|
|
|
|
|
2010-04-09 22:52:44 +04:00
|
|
|
c->status = CONTENT_STATUS_READY;
|
|
|
|
content_update_status(c);
|
|
|
|
content_broadcast(c, CONTENT_MSG_READY, msg_data);
|
|
|
|
}
|
2007-01-13 03:21:15 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Put a content in status CONTENT_STATUS_DONE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void content_set_done(struct content *c)
|
|
|
|
{
|
|
|
|
union content_msg_data msg_data;
|
|
|
|
|
|
|
|
c->status = CONTENT_STATUS_DONE;
|
2007-01-30 18:32:31 +03:00
|
|
|
c->time = wallclock() - c->time;
|
2007-01-13 03:21:15 +03:00
|
|
|
content_update_status(c);
|
|
|
|
content_broadcast(c, CONTENT_MSG_DONE, msg_data);
|
2003-02-09 15:58:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2003-09-08 01:08:13 +04:00
|
|
|
* Reformat to new size.
|
|
|
|
*
|
|
|
|
* Calls the reformat function for the content.
|
2003-02-09 15:58:15 +03:00
|
|
|
*/
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
void content_reformat(hlcache_handle *h, int width, int height)
|
|
|
|
{
|
|
|
|
content__reformat(hlcache_handle_get_content(h), width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
void content__reformat(struct content *c, int width, int height)
|
2003-02-09 15:58:15 +03:00
|
|
|
{
|
2004-04-25 03:42:32 +04:00
|
|
|
union content_msg_data data;
|
2003-02-09 15:58:15 +03:00
|
|
|
assert(c != 0);
|
2003-06-17 23:24:21 +04:00
|
|
|
assert(c->status == CONTENT_STATUS_READY ||
|
|
|
|
c->status == CONTENT_STATUS_DONE);
|
2011-02-28 22:58:08 +03:00
|
|
|
assert(c->locked == false);
|
2010-03-28 16:56:39 +04:00
|
|
|
LOG(("%p %s", c, llcache_handle_get_url(c->llcache)));
|
2005-07-06 02:43:38 +04:00
|
|
|
c->locked = true;
|
2003-04-15 21:53:00 +04:00
|
|
|
c->available_width = width;
|
2004-03-11 05:19:14 +03:00
|
|
|
if (handler_map[c->type].reformat) {
|
|
|
|
handler_map[c->type].reformat(c, width, height);
|
2004-04-25 03:42:32 +04:00
|
|
|
content_broadcast(c, CONTENT_MSG_REFORMAT, data);
|
2004-03-11 05:19:14 +03:00
|
|
|
}
|
2005-07-06 02:43:38 +04:00
|
|
|
c->locked = false;
|
2003-02-09 15:58:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2003-09-08 01:08:13 +04:00
|
|
|
* Destroy and free a content.
|
|
|
|
*
|
|
|
|
* Calls the destroy function for the content, and frees the structure.
|
2003-02-09 15:58:15 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
void content_destroy(struct content *c)
|
|
|
|
{
|
2004-01-26 17:16:23 +03:00
|
|
|
assert(c);
|
2010-03-28 16:56:39 +04:00
|
|
|
LOG(("content %p %s", c, llcache_handle_get_url(c->llcache)));
|
2011-02-28 22:58:08 +03:00
|
|
|
assert(c->locked == false);
|
2004-01-26 17:16:23 +03:00
|
|
|
|
2004-03-11 05:19:14 +03:00
|
|
|
if (c->type < HANDLER_MAP_COUNT && handler_map[c->type].destroy)
|
2003-06-17 23:24:21 +04:00
|
|
|
handler_map[c->type].destroy(c);
|
2010-04-12 00:58:50 +04:00
|
|
|
|
|
|
|
llcache_handle_release(c->llcache);
|
|
|
|
c->llcache = NULL;
|
|
|
|
|
2005-04-03 14:58:49 +04:00
|
|
|
talloc_free(c);
|
2003-02-09 15:58:15 +03:00
|
|
|
}
|
|
|
|
|
2010-06-04 13:35:08 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle mouse movements in a content window.
|
|
|
|
*
|
|
|
|
* \param h Content handle
|
|
|
|
* \param bw browser window
|
|
|
|
* \param mouse state of mouse buttons and modifier keys
|
|
|
|
* \param x coordinate of mouse
|
|
|
|
* \param y coordinate of mouse
|
|
|
|
*/
|
|
|
|
|
|
|
|
void content_mouse_track(hlcache_handle *h, struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y)
|
|
|
|
{
|
|
|
|
struct content *c = hlcache_handle_get_content(h);
|
|
|
|
assert(c != NULL);
|
|
|
|
|
|
|
|
if (handler_map[c->type].mouse_track)
|
|
|
|
handler_map[c->type].mouse_track(c, bw, mouse, x, y);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle mouse clicks and movements in a content window.
|
|
|
|
*
|
|
|
|
* \param h Content handle
|
|
|
|
* \param bw browser window
|
|
|
|
* \param mouse state of mouse buttons and modifier keys
|
|
|
|
* \param x coordinate of mouse
|
|
|
|
* \param y coordinate of mouse
|
|
|
|
*
|
|
|
|
* This function handles both hovering and clicking. It is important that the
|
|
|
|
* code path is identical (except that hovering doesn't carry out the action),
|
|
|
|
* so that the status bar reflects exactly what will happen. Having separate
|
|
|
|
* code paths opens the possibility that an attacker will make the status bar
|
|
|
|
* show some harmless action where clicking will be harmful.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void content_mouse_action(hlcache_handle *h, struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y)
|
|
|
|
{
|
|
|
|
struct content *c = hlcache_handle_get_content(h);
|
|
|
|
assert(c != NULL);
|
|
|
|
|
|
|
|
if (handler_map[c->type].mouse_action)
|
|
|
|
handler_map[c->type].mouse_action(c, bw, mouse, x, y);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-23 23:46:29 +03:00
|
|
|
/**
|
2010-03-28 16:56:39 +04:00
|
|
|
* Request a redraw of an area of a content
|
2004-01-23 23:46:29 +03:00
|
|
|
*
|
2010-03-28 20:00:54 +04:00
|
|
|
* \param h Content handle
|
|
|
|
* \param x x co-ord of left edge
|
|
|
|
* \param y y co-ord of top edge
|
|
|
|
* \param width Width of rectangle
|
2010-03-28 16:56:39 +04:00
|
|
|
* \param height Height of rectangle
|
2004-01-23 23:46:29 +03:00
|
|
|
*/
|
2010-03-28 16:56:39 +04:00
|
|
|
void content_request_redraw(struct hlcache_handle *h,
|
|
|
|
int x, int y, int width, int height)
|
2004-01-23 23:46:29 +03:00
|
|
|
{
|
2010-03-28 16:56:39 +04:00
|
|
|
struct content *c = hlcache_handle_get_content(h);
|
|
|
|
union content_msg_data data;
|
2004-01-23 23:46:29 +03:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
if (c == NULL)
|
|
|
|
return;
|
2004-01-23 23:46:29 +03:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
data.redraw.x = x;
|
|
|
|
data.redraw.y = y;
|
|
|
|
data.redraw.width = width;
|
|
|
|
data.redraw.height = height;
|
2004-07-30 20:16:07 +04:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
data.redraw.full_redraw = true;
|
2004-07-30 20:16:07 +04:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
data.redraw.object = c;
|
|
|
|
data.redraw.object_x = 0;
|
|
|
|
data.redraw.object_y = 0;
|
|
|
|
data.redraw.object_width = c->width;
|
|
|
|
data.redraw.object_height = c->height;
|
2004-07-30 20:16:07 +04:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
content_broadcast(c, CONTENT_MSG_REDRAW, data);
|
|
|
|
}
|
2004-07-30 20:16:07 +04:00
|
|
|
|
2003-05-10 15:15:49 +04:00
|
|
|
/**
|
2003-09-08 01:08:13 +04:00
|
|
|
* Display content on screen.
|
|
|
|
*
|
|
|
|
* Calls the redraw function for the content, if it exists.
|
2009-02-02 17:06:51 +03:00
|
|
|
*
|
2010-03-28 16:56:39 +04:00
|
|
|
* \param h content
|
2009-02-02 17:06:51 +03:00
|
|
|
* \param x coordinate for top-left of redraw
|
|
|
|
* \param y coordinate for top-left of redraw
|
2011-02-11 13:55:46 +03:00
|
|
|
* \param width render width (not used for HTML redraw)
|
|
|
|
* \param height render height (not used for HTML redraw)
|
2011-02-14 01:25:11 +03:00
|
|
|
* \param clip clip rectangle
|
2009-02-02 17:06:51 +03:00
|
|
|
* \param scale scale for redraw
|
|
|
|
* \param background_colour the background colour
|
|
|
|
* \return true if successful, false otherwise
|
|
|
|
*
|
2011-02-14 01:25:11 +03:00
|
|
|
* x, y and clip are coordinates from the top left of the canvas area.
|
2009-02-02 17:06:51 +03:00
|
|
|
*
|
2011-02-14 01:25:11 +03:00
|
|
|
* The top left corner of the clip rectangle is (x0, y0) and
|
|
|
|
* the bottom right corner of the clip rectangle is (x1, y1).
|
|
|
|
* Units for x, y and clip are pixels.
|
2011-02-11 13:55:46 +03:00
|
|
|
*
|
|
|
|
* Content scaling is handled differently for contents with and without
|
|
|
|
* intrinsic dimensions.
|
|
|
|
*
|
|
|
|
* Content without intrinsic dimensions, e.g. HTML:
|
|
|
|
* The scale value is applied (the content having been reformatted
|
|
|
|
* appropriately beforehand). The width and height are not used.
|
|
|
|
*
|
|
|
|
* Content with intrinsic dimensions, e.g. images:
|
|
|
|
* The scale value is not used. The content is scaled from its own
|
|
|
|
* intrinsic dimensions to the passed render width and height.
|
2003-05-10 15:15:49 +04:00
|
|
|
*/
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
bool content_redraw(hlcache_handle *h, int x, int y,
|
2011-02-14 22:17:08 +03:00
|
|
|
int width, int height, const struct rect *clip,
|
2008-09-29 02:37:13 +04:00
|
|
|
float scale, colour background_colour)
|
2003-05-10 15:15:49 +04:00
|
|
|
{
|
2010-03-28 16:56:39 +04:00
|
|
|
struct content *c = hlcache_handle_get_content(h);
|
2003-05-10 15:15:49 +04:00
|
|
|
assert(c != 0);
|
2011-02-11 01:35:41 +03:00
|
|
|
|
|
|
|
if (c->locked) {
|
2005-07-06 02:43:38 +04:00
|
|
|
/* not safe to attempt redraw */
|
|
|
|
return true;
|
2011-02-11 01:35:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handler_map[c->type].redraw == NULL) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return handler_map[c->type].redraw(c, x, y, width, height,
|
2011-02-14 01:25:11 +03:00
|
|
|
clip, scale, background_colour);
|
2006-02-21 23:49:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Display content on screen with optional tiling.
|
|
|
|
*
|
|
|
|
* Calls the redraw_tile function for the content, or emulates it with the
|
|
|
|
* redraw function if it doesn't exist.
|
|
|
|
*/
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
bool content_redraw_tiled(hlcache_handle *h, int x, int y,
|
2011-02-14 22:17:08 +03:00
|
|
|
int width, int height, const struct rect *clip,
|
2008-09-29 02:37:13 +04:00
|
|
|
float scale, colour background_colour,
|
2006-02-21 23:49:12 +03:00
|
|
|
bool repeat_x, bool repeat_y)
|
|
|
|
{
|
2010-03-28 16:56:39 +04:00
|
|
|
struct content *c = hlcache_handle_get_content(h);
|
2006-02-21 23:49:12 +03:00
|
|
|
int x0, y0, x1, y1;
|
|
|
|
|
|
|
|
assert(c != 0);
|
|
|
|
|
2007-03-19 02:48:12 +03:00
|
|
|
// LOG(("%p %s", c, c->url));
|
2007-03-18 20:04:18 +03:00
|
|
|
|
2006-02-21 23:49:12 +03:00
|
|
|
if (c->locked)
|
|
|
|
/* not safe to attempt redraw */
|
|
|
|
return true;
|
|
|
|
if (handler_map[c->type].redraw_tiled) {
|
|
|
|
return handler_map[c->type].redraw_tiled(c, x, y, width, height,
|
2011-02-14 01:25:11 +03:00
|
|
|
clip, scale, background_colour,
|
|
|
|
repeat_x, repeat_y);
|
2006-02-21 23:49:12 +03:00
|
|
|
} else {
|
2010-03-28 20:00:54 +04:00
|
|
|
/* ensure we have a redrawable content */
|
2006-02-21 23:49:12 +03:00
|
|
|
if ((!handler_map[c->type].redraw) || (width == 0) ||
|
|
|
|
(height == 0))
|
|
|
|
return true;
|
|
|
|
/* simple optimisation for no repeat (common for backgrounds) */
|
2009-11-22 17:24:53 +03:00
|
|
|
if ((!repeat_x) && (!repeat_y))
|
2006-02-21 23:49:12 +03:00
|
|
|
return handler_map[c->type].redraw(c, x, y, width,
|
2011-02-14 01:25:11 +03:00
|
|
|
height, clip, scale, background_colour);
|
2006-02-21 23:49:12 +03:00
|
|
|
/* find the redraw boundaries to loop within*/
|
|
|
|
x0 = x;
|
|
|
|
if (repeat_x) {
|
2011-02-14 01:25:11 +03:00
|
|
|
for (; x0 > clip->x0; x0 -= width);
|
|
|
|
x1 = clip->x1;
|
2006-02-21 23:49:12 +03:00
|
|
|
} else {
|
|
|
|
x1 = x + 1;
|
|
|
|
}
|
|
|
|
y0 = y;
|
|
|
|
if (repeat_y) {
|
2011-02-14 01:25:11 +03:00
|
|
|
for (; y0 > clip->y0; y0 -= height);
|
|
|
|
y1 = clip->y1;
|
2006-02-21 23:49:12 +03:00
|
|
|
} else {
|
|
|
|
y1 = y + 1;
|
|
|
|
}
|
|
|
|
/* repeatedly plot our content */
|
|
|
|
for (y = y0; y < y1; y += height)
|
|
|
|
for (x = x0; x < x1; x += width)
|
|
|
|
if (!handler_map[c->type].redraw(c, x, y,
|
2011-02-14 01:25:11 +03:00
|
|
|
width, height, clip,
|
2006-02-21 23:49:12 +03:00
|
|
|
scale, background_colour))
|
|
|
|
return false;
|
|
|
|
}
|
2004-08-11 20:26:13 +04:00
|
|
|
return true;
|
2003-05-10 15:15:49 +04:00
|
|
|
}
|
|
|
|
|
2003-06-17 23:24:21 +04:00
|
|
|
|
|
|
|
/**
|
2003-09-08 01:08:13 +04:00
|
|
|
* Register a user for callbacks.
|
|
|
|
*
|
2006-02-21 23:49:12 +03:00
|
|
|
* \param c the content to register
|
2005-01-14 01:42:39 +03:00
|
|
|
* \param callback the callback function
|
2010-03-28 20:00:54 +04:00
|
|
|
* \param pw callback private data
|
2005-01-14 01:42:39 +03:00
|
|
|
* \return true on success, false otherwise on memory exhaustion
|
2005-01-02 06:58:21 +03:00
|
|
|
*
|
2010-03-28 16:56:39 +04:00
|
|
|
* The callback will be called when content_broadcast() is
|
2003-09-08 01:08:13 +04:00
|
|
|
* called with the content.
|
2003-06-17 23:24:21 +04:00
|
|
|
*/
|
|
|
|
|
2005-01-02 06:58:21 +03:00
|
|
|
bool content_add_user(struct content *c,
|
2010-03-28 16:56:39 +04:00
|
|
|
void (*callback)(struct content *c, content_msg msg,
|
|
|
|
union content_msg_data data, void *pw),
|
|
|
|
void *pw)
|
2003-06-17 23:24:21 +04:00
|
|
|
{
|
|
|
|
struct content_user *user;
|
2005-01-02 06:58:21 +03:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
LOG(("content %s (%p), user %p %p",
|
|
|
|
llcache_handle_get_url(c->llcache), c, callback, pw));
|
2005-04-03 14:58:49 +04:00
|
|
|
user = talloc(c, struct content_user);
|
2005-01-14 01:42:39 +03:00
|
|
|
if (!user)
|
2005-01-02 06:58:21 +03:00
|
|
|
return false;
|
2003-06-17 23:24:21 +04:00
|
|
|
user->callback = callback;
|
2010-03-28 16:56:39 +04:00
|
|
|
user->pw = pw;
|
2003-06-17 23:24:21 +04:00
|
|
|
user->next = c->user_list->next;
|
|
|
|
c->user_list->next = user;
|
2005-01-02 06:58:21 +03:00
|
|
|
|
|
|
|
return true;
|
2003-06-17 23:24:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2003-09-08 01:08:13 +04:00
|
|
|
* Remove a callback user.
|
|
|
|
*
|
2010-03-28 16:56:39 +04:00
|
|
|
* The callback function and pw must be identical to those passed to
|
2003-09-08 01:08:13 +04:00
|
|
|
* content_add_user().
|
2003-06-17 23:24:21 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
void content_remove_user(struct content *c,
|
2010-03-28 16:56:39 +04:00
|
|
|
void (*callback)(struct content *c, content_msg msg,
|
|
|
|
union content_msg_data data, void *pw),
|
|
|
|
void *pw)
|
2003-06-17 23:24:21 +04:00
|
|
|
{
|
|
|
|
struct content_user *user, *next;
|
2010-03-28 16:56:39 +04:00
|
|
|
LOG(("content %s (%p), user %p %p",
|
|
|
|
llcache_handle_get_url(c->llcache), c, callback, pw));
|
2003-06-17 23:24:21 +04:00
|
|
|
|
|
|
|
/* user_list starts with a sentinel */
|
|
|
|
for (user = c->user_list; user->next != 0 &&
|
|
|
|
!(user->next->callback == callback &&
|
2010-03-28 16:56:39 +04:00
|
|
|
user->next->pw == pw); user = user->next)
|
2003-06-17 23:24:21 +04:00
|
|
|
;
|
|
|
|
if (user->next == 0) {
|
|
|
|
LOG(("user not found in list"));
|
|
|
|
assert(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
next = user->next;
|
|
|
|
user->next = next->next;
|
2005-04-03 14:58:49 +04:00
|
|
|
talloc_free(next);
|
2003-06-17 23:24:21 +04:00
|
|
|
}
|
|
|
|
|
2010-04-04 16:41:19 +04:00
|
|
|
/**
|
|
|
|
* Count users for the content.
|
|
|
|
*/
|
|
|
|
|
|
|
|
uint32_t content_count_users(struct content *c)
|
|
|
|
{
|
|
|
|
struct content_user *user;
|
|
|
|
uint32_t counter = 0;
|
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
|
|
|
|
for (user = c->user_list; user != NULL; user = user->next)
|
|
|
|
counter += 1;
|
|
|
|
|
|
|
|
return counter - 1; /* Subtract 1 for the sentinel */
|
|
|
|
}
|
2003-06-17 23:24:21 +04:00
|
|
|
|
2010-04-11 20:34:23 +04:00
|
|
|
/**
|
|
|
|
* Determine if quirks mode matches
|
|
|
|
*
|
|
|
|
* \param c Content to consider
|
|
|
|
* \param quirks Quirks mode to match
|
|
|
|
* \return True if quirks match, false otherwise
|
|
|
|
*/
|
|
|
|
bool content_matches_quirks(struct content *c, bool quirks)
|
|
|
|
{
|
|
|
|
/* If the content isn't CSS, we don't care about quirks */
|
|
|
|
if (c->type != CONTENT_CSS)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return c->quirks == quirks;
|
|
|
|
}
|
|
|
|
|
2010-04-11 20:37:39 +04:00
|
|
|
/**
|
|
|
|
* Determine if a content is shareable
|
|
|
|
*
|
|
|
|
* \param c Content to consider
|
|
|
|
* \return True if content is shareable, false otherwise
|
|
|
|
*/
|
|
|
|
bool content_is_shareable(struct content *c)
|
|
|
|
{
|
|
|
|
return handler_map[c->type].no_share == false;
|
|
|
|
}
|
|
|
|
|
2003-06-17 23:24:21 +04:00
|
|
|
/**
|
2003-09-08 01:08:13 +04:00
|
|
|
* Send a message to all users.
|
2003-06-17 23:24:21 +04:00
|
|
|
*/
|
|
|
|
|
2004-04-25 03:42:32 +04:00
|
|
|
void content_broadcast(struct content *c, content_msg msg,
|
|
|
|
union content_msg_data data)
|
2003-06-17 23:24:21 +04:00
|
|
|
{
|
|
|
|
struct content_user *user, *next;
|
2005-01-13 23:26:16 +03:00
|
|
|
assert(c);
|
2007-03-19 02:48:12 +03:00
|
|
|
// LOG(("%p %s -> %d", c, c->url, msg));
|
2003-06-17 23:24:21 +04:00
|
|
|
for (user = c->user_list->next; user != 0; user = next) {
|
|
|
|
next = user->next; /* user may be destroyed during callback */
|
|
|
|
if (user->callback != 0)
|
2010-03-28 16:56:39 +04:00
|
|
|
user->callback(c, msg, data, user->pw);
|
2003-06-17 23:24:21 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-07-15 02:57:45 +04:00
|
|
|
|
2003-09-08 01:08:13 +04:00
|
|
|
/**
|
2004-08-12 02:08:26 +04:00
|
|
|
* A window containing the content has been opened.
|
2003-09-08 01:08:13 +04:00
|
|
|
*
|
2006-02-21 23:49:12 +03:00
|
|
|
* \param c content that has been opened
|
|
|
|
* \param bw browser window containing the content
|
|
|
|
* \param page content of type CONTENT_HTML containing c, or 0 if not an
|
|
|
|
* object within a page
|
2005-10-31 00:22:19 +03:00
|
|
|
* \param index index in page->data.html.object, or 0 if not an object
|
2006-02-21 23:49:12 +03:00
|
|
|
* \param box box containing c, or 0 if not an object
|
2005-10-31 00:22:19 +03:00
|
|
|
* \param params object parameters, or 0 if not an object
|
|
|
|
*
|
2004-08-12 02:08:26 +04:00
|
|
|
* Calls the open function for the content.
|
2003-09-08 01:08:13 +04:00
|
|
|
*/
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
void content_open(hlcache_handle *h, struct browser_window *bw,
|
2005-10-31 00:22:19 +03:00
|
|
|
struct content *page, unsigned int index, struct box *box,
|
2004-08-12 02:08:26 +04:00
|
|
|
struct object_params *params)
|
2003-07-15 02:57:45 +04:00
|
|
|
{
|
2010-03-28 16:56:39 +04:00
|
|
|
struct content *c = hlcache_handle_get_content(h);
|
2003-07-15 02:57:45 +04:00
|
|
|
assert(c != 0);
|
|
|
|
assert(c->type < CONTENT_UNKNOWN);
|
2010-03-28 16:56:39 +04:00
|
|
|
LOG(("content %p %s", c, llcache_handle_get_url(c->llcache)));
|
2004-08-12 02:08:26 +04:00
|
|
|
if (handler_map[c->type].open)
|
2005-10-31 00:22:19 +03:00
|
|
|
handler_map[c->type].open(c, bw, page, index, box, params);
|
2003-07-15 02:57:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-09-08 01:08:13 +04:00
|
|
|
/**
|
2004-08-12 02:08:26 +04:00
|
|
|
* The window containing the content has been closed.
|
2003-09-08 01:08:13 +04:00
|
|
|
*
|
2004-08-12 02:08:26 +04:00
|
|
|
* Calls the close function for the content.
|
2003-09-08 01:08:13 +04:00
|
|
|
*/
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
void content_close(hlcache_handle *h)
|
2003-07-15 02:57:45 +04:00
|
|
|
{
|
2010-03-28 16:56:39 +04:00
|
|
|
struct content *c = hlcache_handle_get_content(h);
|
2003-07-15 02:57:45 +04:00
|
|
|
assert(c != 0);
|
|
|
|
assert(c->type < CONTENT_UNKNOWN);
|
2010-03-28 16:56:39 +04:00
|
|
|
LOG(("content %p %s", c, llcache_handle_get_url(c->llcache)));
|
2004-08-12 02:08:26 +04:00
|
|
|
if (handler_map[c->type].close)
|
|
|
|
handler_map[c->type].close(c);
|
2003-07-15 02:57:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-11 00:41:26 +04:00
|
|
|
void content_add_error(struct content *c, const char *token,
|
|
|
|
unsigned int line)
|
|
|
|
{
|
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2010-04-03 15:55:28 +04:00
|
|
|
bool content__set_title(struct content *c, const char *title)
|
|
|
|
{
|
|
|
|
char *new_title = talloc_strdup(c, title);
|
|
|
|
if (new_title == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (c->title != NULL)
|
|
|
|
talloc_free(c->title);
|
|
|
|
|
|
|
|
c->title = new_title;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
/**
|
|
|
|
* Retrieve type of content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve type of
|
|
|
|
* \return Content type
|
|
|
|
*/
|
|
|
|
content_type content_get_type(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_type(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
content_type content__get_type(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return CONTENT_UNKNOWN;
|
|
|
|
|
|
|
|
return c->type;
|
|
|
|
}
|
|
|
|
|
2010-04-07 13:12:09 +04:00
|
|
|
/**
|
|
|
|
* Retrieve mime-type of content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve mime-type of
|
|
|
|
* \return Pointer to mime-type, or NULL if not found.
|
|
|
|
*/
|
|
|
|
const char *content_get_mime_type(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_mime_type(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *content__get_mime_type(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return c->mime_type;
|
|
|
|
}
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
/**
|
|
|
|
* Retrieve URL associated with content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve URL from
|
|
|
|
* \return Pointer to URL, or NULL if not found.
|
|
|
|
*/
|
|
|
|
const char *content_get_url(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_url(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *content__get_url(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return llcache_handle_get_url(c->llcache);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve title associated with content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve title from
|
|
|
|
* \return Pointer to title, or NULL if not found.
|
|
|
|
*/
|
|
|
|
const char *content_get_title(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_title(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *content__get_title(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return c->title != NULL ? c->title : llcache_handle_get_url(c->llcache);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve status of content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve status of
|
|
|
|
* \return Content status
|
|
|
|
*/
|
|
|
|
content_status content_get_status(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_status(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
content_status content__get_status(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
2011-02-28 23:38:23 +03:00
|
|
|
return CONTENT_STATUS_ERROR;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
return c->status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve status message associated with content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve status message from
|
|
|
|
* \return Pointer to status message, or NULL if not found.
|
|
|
|
*/
|
|
|
|
const char *content_get_status_message(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_status_message(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *content__get_status_message(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return c->status_message;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve width of content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve width of
|
|
|
|
* \return Content width
|
|
|
|
*/
|
|
|
|
int content_get_width(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_width(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
int content__get_width(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return c->width;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve height of content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve height of
|
|
|
|
* \return Content height
|
|
|
|
*/
|
|
|
|
int content_get_height(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_height(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
int content__get_height(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return c->height;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve available width of content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve available width of
|
|
|
|
* \return Available width of content
|
|
|
|
*/
|
|
|
|
int content_get_available_width(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_available_width(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
int content__get_available_width(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return c->available_width;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve source of content
|
|
|
|
*
|
2010-03-28 20:00:54 +04:00
|
|
|
* \param c Content to retrieve source of
|
|
|
|
* \param size Pointer to location to receive byte size of source
|
2010-03-28 16:56:39 +04:00
|
|
|
* \return Pointer to source data
|
|
|
|
*/
|
|
|
|
const char *content_get_source_data(hlcache_handle *h, unsigned long *size)
|
|
|
|
{
|
|
|
|
return content__get_source_data(hlcache_handle_get_content(h), size);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *content__get_source_data(struct content *c, unsigned long *size)
|
|
|
|
{
|
|
|
|
const uint8_t *data;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
assert(size != NULL);
|
|
|
|
|
|
|
|
if (c == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
data = llcache_handle_get_source_data(c->llcache, &len);
|
|
|
|
|
|
|
|
*size = (unsigned long) len;
|
|
|
|
|
|
|
|
return (const char *) data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Invalidate content reuse data: causes subsequent requests for content URL
|
|
|
|
* to query server to determine if content can be reused. This is required
|
|
|
|
* behaviour for forced reloads etc.
|
|
|
|
*
|
|
|
|
* \param c Content to invalidate
|
|
|
|
*/
|
|
|
|
void content_invalidate_reuse_data(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
content__invalidate_reuse_data(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
void content__invalidate_reuse_data(struct content *c)
|
|
|
|
{
|
2010-04-17 00:43:36 +04:00
|
|
|
if (c == NULL || c->llcache == NULL)
|
2010-03-28 16:56:39 +04:00
|
|
|
return;
|
|
|
|
|
2010-04-17 00:43:36 +04:00
|
|
|
/* Invalidate low-level cache data */
|
|
|
|
llcache_handle_invalidate_cache_data(c->llcache);
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve the refresh URL for a content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve refresh URL from
|
|
|
|
* \return Pointer to URL, or NULL if none
|
|
|
|
*/
|
|
|
|
const char *content_get_refresh_url(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_refresh_url(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *content__get_refresh_url(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return c->refresh;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve the bitmap contained in an image content
|
|
|
|
*
|
|
|
|
* \param c Content to retrieve bitmap from
|
|
|
|
* \return Pointer to bitmap, or NULL if none.
|
|
|
|
*/
|
|
|
|
struct bitmap *content_get_bitmap(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__get_bitmap(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
struct bitmap *content__get_bitmap(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return c->bitmap;
|
|
|
|
}
|
|
|
|
|
2010-04-17 00:54:57 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve quirkiness of a content
|
|
|
|
*
|
|
|
|
* \param h Content to examine
|
|
|
|
* \return True if content is quirky, false otherwise
|
|
|
|
*/
|
|
|
|
bool content_get_quirks(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
struct content *c = hlcache_handle_get_content(h);
|
|
|
|
|
|
|
|
if (c == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return c->quirks;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-07 22:50:18 +04:00
|
|
|
/**
|
|
|
|
* Return whether a content is currently locked
|
|
|
|
*
|
|
|
|
* \param c Content to test
|
|
|
|
* \return true iff locked, else false
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool content_is_locked(hlcache_handle *h)
|
|
|
|
{
|
|
|
|
return content__is_locked(hlcache_handle_get_content(h));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool content__is_locked(struct content *c)
|
|
|
|
{
|
|
|
|
return c->locked;
|
|
|
|
}
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
/**
|
|
|
|
* Retrieve the low-level cache handle for a content
|
|
|
|
*
|
|
|
|
* \param h Content to retrieve from
|
|
|
|
* \return Low-level cache handle
|
|
|
|
*/
|
|
|
|
const llcache_handle *content_get_llcache_handle(struct content *c)
|
|
|
|
{
|
|
|
|
if (c == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return c->llcache;
|
|
|
|
}
|
|
|
|
|
2010-04-04 16:41:19 +04:00
|
|
|
/**
|
|
|
|
* Clone a content object in its current state.
|
|
|
|
*
|
|
|
|
* \param c Content to clone
|
|
|
|
* \return Clone of \a c
|
|
|
|
*/
|
|
|
|
struct content *content_clone(struct content *c)
|
|
|
|
{
|
|
|
|
struct content *nc = talloc_zero(0, struct content);
|
|
|
|
|
|
|
|
if (nc == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (llcache_handle_clone(c->llcache, &(nc->llcache)) != NSERROR_OK) {
|
|
|
|
content_destroy(nc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
llcache_handle_change_callback(nc->llcache,
|
|
|
|
content_llcache_callback, nc);
|
|
|
|
|
|
|
|
nc->type = c->type;
|
|
|
|
|
|
|
|
if (c->mime_type != NULL) {
|
|
|
|
nc->mime_type = talloc_strdup(nc, c->mime_type);
|
|
|
|
if (nc->mime_type == NULL) {
|
|
|
|
content_destroy(nc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nc->status = c->status;
|
|
|
|
|
|
|
|
nc->width = c->width;
|
|
|
|
nc->height = c->height;
|
|
|
|
nc->available_width = c->available_width;
|
|
|
|
nc->quirks = c->quirks;
|
|
|
|
|
|
|
|
if (c->fallback_charset != NULL) {
|
|
|
|
nc->fallback_charset = talloc_strdup(nc, c->fallback_charset);
|
|
|
|
if (nc->fallback_charset == NULL) {
|
|
|
|
content_destroy(nc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c->refresh != NULL) {
|
|
|
|
nc->refresh = talloc_strdup(nc, c->refresh);
|
|
|
|
if (nc->refresh == NULL) {
|
|
|
|
content_destroy(nc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nc->time = c->time;
|
|
|
|
nc->reformat_time = c->reformat_time;
|
|
|
|
nc->size = c->size;
|
|
|
|
nc->talloc_size = c->talloc_size;
|
|
|
|
|
|
|
|
if (c->title != NULL) {
|
|
|
|
nc->title = talloc_strdup(nc, c->title);
|
|
|
|
if (nc->title == NULL) {
|
|
|
|
content_destroy(nc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nc->active = c->active;
|
|
|
|
|
|
|
|
memcpy(&(nc->status_message), &(c->status_message), 120);
|
|
|
|
memcpy(&(nc->sub_status), &(c->sub_status), 80);
|
|
|
|
|
|
|
|
nc->locked = c->locked;
|
|
|
|
nc->total_size = c->total_size;
|
|
|
|
nc->http_code = c->http_code;
|
|
|
|
|
|
|
|
/* Duplicate the data member (and bitmap, if appropriate) */
|
|
|
|
if (handler_map[nc->type].clone != NULL) {
|
|
|
|
if (handler_map[nc->type].clone(c, nc) == false) {
|
|
|
|
content_destroy(nc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Abort a content object
|
|
|
|
*
|
|
|
|
* \param c The content object to abort
|
|
|
|
* \return NSERROR_OK on success, otherwise appropriate error
|
|
|
|
*/
|
|
|
|
nserror content_abort(struct content *c)
|
|
|
|
{
|
|
|
|
LOG(("Aborting %p", c));
|
|
|
|
|
|
|
|
if (c->status == CONTENT_STATUS_READY) {
|
|
|
|
switch (c->type) {
|
|
|
|
case CONTENT_HTML:
|
|
|
|
html_stop(c);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(("Unable to abort sub-parts for type %d", c->type));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* And for now, abort our llcache object */
|
|
|
|
return llcache_handle_abort(c->llcache);
|
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|