Consider stylesheet media types

svn path=/trunk/netsurf/; revision=8820
This commit is contained in:
John Mark Bell 2009-07-27 13:49:10 +00:00
parent e5f55a27ef
commit b5d55eb295
5 changed files with 170 additions and 143 deletions

View File

@ -57,9 +57,10 @@ bool nscss_create(struct content *c, struct content *parent,
const char *params[])
{
css_origin origin = CSS_ORIGIN_AUTHOR;
css_media_type media = CSS_MEDIA_ALL;
uint64_t media = CSS_MEDIA_ALL;
lwc_context *dict = NULL;
bool quirks = true;
uint32_t i;
union content_msg_data msg_data;
css_error error;
@ -75,18 +76,23 @@ bool nscss_create(struct content *c, struct content *parent,
assert(parent->data.html.dict != NULL);
if (c == parent->data.html.
stylesheet_content[STYLESHEET_BASE] ||
stylesheets[STYLESHEET_BASE].c ||
c == parent->data.html.
stylesheet_content[STYLESHEET_QUIRKS] ||
stylesheets[STYLESHEET_QUIRKS].c ||
c == parent->data.html.
stylesheet_content[STYLESHEET_ADBLOCK])
stylesheets[STYLESHEET_ADBLOCK].c)
origin = CSS_ORIGIN_UA;
/** \todo media types */
quirks = (parent->data.html.quirks !=
BINDING_QUIRKS_MODE_NONE);
for (i = 0; i < parent->data.html.stylesheet_count;
i++) {
if (parent->data.html.stylesheets[i].c == c)
media = parent->data.html.
stylesheets[i].media;
}
dict = parent->data.html.dict;
} else {
assert(parent->data.css.sheet != NULL);
@ -110,7 +116,11 @@ bool nscss_create(struct content *c, struct content *parent,
return false;
}
/** \todo media types */
for (i = 0; i < parent->data.css.import_count; i++) {
if (parent->data.css.imports[i].c == c)
media = parent->data.css.
imports[i].media;
}
dict = parent->data.css.dict;
}
@ -188,7 +198,7 @@ bool nscss_convert(struct content *c, int w, int h)
/* Process pending imports */
while (error == CSS_IMPORTS_PENDING) {
struct content **imports;
struct nscss_import *imports;
uint32_t i;
lwc_string *uri;
uint64_t media;
@ -212,7 +222,7 @@ bool nscss_convert(struct content *c, int w, int h)
/* Increase space in table */
imports = realloc(c->data.css.imports,
(c->data.css.import_count + 1) *
sizeof(struct content *));
sizeof(struct nscss_import));
if (imports == NULL) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
@ -223,12 +233,13 @@ bool nscss_convert(struct content *c, int w, int h)
/* Create content */
i = c->data.css.import_count;
c->data.css.imports[c->data.css.import_count++] =
c->data.css.imports[c->data.css.import_count].media = media;
c->data.css.imports[c->data.css.import_count++].c =
fetchcache(lwc_string_data(uri),
nscss_import, (intptr_t) c, i,
c->width, c->height, true, NULL, NULL,
false, false);
if (c->data.css.imports[i] == NULL) {
if (c->data.css.imports[i].c == NULL) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
c->status = CONTENT_STATUS_ERROR;
@ -237,7 +248,7 @@ bool nscss_convert(struct content *c, int w, int h)
/* Fetch content */
c->active++;
fetchcache_go(c->data.css.imports[i], c->url,
fetchcache_go(c->data.css.imports[i].c, c->url,
nscss_import, (intptr_t) c, i,
c->width, c->height, NULL, NULL, false, c);
@ -247,9 +258,9 @@ bool nscss_convert(struct content *c, int w, int h)
gui_multitask();
}
if (c->data.css.imports[i] != NULL) {
sheet = c->data.css.imports[i]->data.css.sheet;
c->data.css.imports[i]->data.css.sheet = NULL;
if (c->data.css.imports[i].c != NULL) {
sheet = c->data.css.imports[i].c->data.css.sheet;
c->data.css.imports[i].c->data.css.sheet = NULL;
} else {
error = css_stylesheet_create(CSS_LEVEL_DEFAULT,
NULL, "", NULL, CSS_ORIGIN_AUTHOR,
@ -297,11 +308,11 @@ void nscss_destroy(struct content *c)
uint32_t i;
for (i = 0; i < c->data.css.import_count; i++) {
if (c->data.css.imports[i] != NULL) {
content_remove_user(c->data.css.imports[i],
if (c->data.css.imports[i].c != NULL) {
content_remove_user(c->data.css.imports[i].c,
nscss_import, (uintptr_t) c, i);
}
c->data.css.imports[i] = NULL;
c->data.css.imports[i].c = NULL;
}
free(c->data.css.imports);
@ -342,7 +353,7 @@ void nscss_import(content_msg msg, struct content *c,
c->status = CONTENT_STATUS_ERROR;
}
parent->data.css.imports[i] = NULL;
parent->data.css.imports[i].c = NULL;
parent->active--;
content_add_error(parent, "NotCSS", 0);
}
@ -356,15 +367,15 @@ void nscss_import(content_msg msg, struct content *c,
case CONTENT_MSG_SSL:
case CONTENT_MSG_LAUNCH:
case CONTENT_MSG_ERROR:
if (parent->data.css.imports[i] == c) {
parent->data.css.imports[i] = NULL;
if (parent->data.css.imports[i].c == c) {
parent->data.css.imports[i].c = NULL;
parent->active--;
}
break;
case CONTENT_MSG_STATUS:
break;
case CONTENT_MSG_NEWPTR:
parent->data.css.imports[i] = c;
parent->data.css.imports[i].c = c;
break;
default:
assert(0);

View File

@ -19,9 +19,12 @@
#ifndef netsurf_css_css_h_
#define netsurf_css_css_h_
#include <stdint.h>
#include <libcss/libcss.h>
struct content;
struct nscss_import;
/**
* CSS content data
@ -33,7 +36,15 @@ struct content_css_data
css_stylesheet *sheet; /**< Stylesheet object */
uint32_t import_count; /**< Number of sheets imported */
struct content **imports; /**< Array of imported sheets */
struct nscss_import *imports; /**< Array of imported sheets */
};
/**
* Imported stylesheet record
*/
struct nscss_import {
struct content *c; /**< Content containing sheet */
uint64_t media; /**< Media types that sheet applies to */
};
bool nscss_create(struct content *c, struct content *parent,

View File

@ -872,8 +872,8 @@ void browser_window_reload(struct browser_window *bw, bool all)
/* invalidate stylesheets */
for (i = STYLESHEET_START; i != c->data.html.stylesheet_count;
i++) {
if (c->data.html.stylesheet_content[i])
c->data.html.stylesheet_content[i]->fresh =
if (c->data.html.stylesheets[i].c)
c->data.html.stylesheets[i].c->fresh =
false;
}
}

View File

@ -132,7 +132,7 @@ bool html_create(struct content *c, struct content *parent,
html->layout = 0;
html->background_colour = NS_TRANSPARENT;
html->stylesheet_count = 0;
html->stylesheet_content = 0;
html->stylesheets = NULL;
html->select_ctx = NULL;
html->object_count = 0;
html->object = 0;
@ -802,62 +802,64 @@ bool html_find_stylesheets(struct content *c, xmlNode *html)
unsigned int last_active = 0;
union content_msg_data msg_data;
url_func_result res;
struct content **stylesheet_content;
struct nscss_import *stylesheets;
css_error error;
/* stylesheet 0 is the base style sheet,
* stylesheet 1 is the quirks mode style sheet,
* stylesheet 2 is the adblocking stylesheet */
c->data.html.stylesheet_content = talloc_array(c, struct content *,
c->data.html.stylesheets = talloc_array(c, struct nscss_import,
STYLESHEET_START);
if (!c->data.html.stylesheet_content)
if (c->data.html.stylesheets == NULL)
goto no_memory;
c->data.html.stylesheet_content[STYLESHEET_QUIRKS] = NULL;
c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] = NULL;
c->data.html.stylesheets[STYLESHEET_BASE].c = NULL;
c->data.html.stylesheets[STYLESHEET_BASE].media = CSS_MEDIA_ALL;
c->data.html.stylesheets[STYLESHEET_QUIRKS].c = NULL;
c->data.html.stylesheets[STYLESHEET_QUIRKS].media = CSS_MEDIA_ALL;
c->data.html.stylesheets[STYLESHEET_ADBLOCK].c = NULL;
c->data.html.stylesheets[STYLESHEET_ADBLOCK].media = CSS_MEDIA_ALL;
c->data.html.stylesheet_count = STYLESHEET_START;
c->active = 0;
c->data.html.stylesheet_content[STYLESHEET_BASE] = fetchcache(
c->data.html.stylesheets[STYLESHEET_BASE].c = fetchcache(
default_stylesheet_url,
html_convert_css_callback, (intptr_t) c,
STYLESHEET_BASE, c->width, c->height,
true, 0, 0, false, false);
if (!c->data.html.stylesheet_content[STYLESHEET_BASE])
if (c->data.html.stylesheets[STYLESHEET_BASE].c == NULL)
goto no_memory;
c->active++;
fetchcache_go(c->data.html.stylesheet_content[STYLESHEET_BASE],
fetchcache_go(c->data.html.stylesheets[STYLESHEET_BASE].c,
c->url, html_convert_css_callback, (intptr_t) c,
STYLESHEET_BASE, c->width, c->height,
0, 0, false, c);
if (c->data.html.quirks == BINDING_QUIRKS_MODE_FULL) {
c->data.html.stylesheet_content[STYLESHEET_QUIRKS] =
c->data.html.stylesheets[STYLESHEET_QUIRKS].c =
fetchcache(quirks_stylesheet_url,
html_convert_css_callback, (intptr_t) c,
STYLESHEET_QUIRKS, c->width, c->height,
true, 0, 0, false, false);
if (c->data.html.stylesheet_content[STYLESHEET_QUIRKS] == NULL)
if (c->data.html.stylesheets[STYLESHEET_QUIRKS].c == NULL)
goto no_memory;
c->active++;
fetchcache_go(c->data.html.
stylesheet_content[STYLESHEET_QUIRKS],
fetchcache_go(c->data.html.stylesheets[STYLESHEET_QUIRKS].c,
c->url, html_convert_css_callback,
(intptr_t) c, STYLESHEET_QUIRKS, c->width,
c->height, 0, 0, false, c);
}
if (option_block_ads) {
c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] =
c->data.html.stylesheets[STYLESHEET_ADBLOCK].c =
fetchcache(adblock_stylesheet_url,
html_convert_css_callback, (intptr_t) c,
STYLESHEET_ADBLOCK, c->width,
c->height, true, 0, 0, false, false);
if (!c->data.html.stylesheet_content[STYLESHEET_ADBLOCK])
if (c->data.html.stylesheets[STYLESHEET_ADBLOCK].c == NULL)
goto no_memory;
c->active++;
fetchcache_go(c->data.html.
stylesheet_content[STYLESHEET_ADBLOCK],
fetchcache_go(c->data.html.stylesheets[STYLESHEET_ADBLOCK].c,
c->url, html_convert_css_callback,
(intptr_t) c, STYLESHEET_ADBLOCK, c->width,
c->height, 0, 0, false, c);
@ -885,7 +887,6 @@ bool html_find_stylesheets(struct content *c, xmlNode *html)
continue;
if (strcmp((const char *) node->name, "link") == 0) {
/* rel=<space separated list, including 'stylesheet'> */
if ((rel = (char *) xmlGetProp(node,
(const xmlChar *) "rel")) == NULL)
@ -913,8 +914,9 @@ bool html_find_stylesheets(struct content *c, xmlNode *html)
/* media contains 'screen' or 'all' or not present */
if ((media = (char *) xmlGetProp(node,
(const xmlChar *) "media")) != NULL) {
if (strcasestr(media, "screen") == 0 &&
strcasestr(media, "all") == 0) {
if (strcasestr(media, "screen") == NULL &&
strcasestr(media, "all") ==
NULL) {
xmlFree(media);
continue;
}
@ -947,25 +949,27 @@ bool html_find_stylesheets(struct content *c, xmlNode *html)
free(url);
/* start fetch */
stylesheet_content = talloc_realloc(c,
c->data.html.stylesheet_content,
struct content *, i + 1);
if (!stylesheet_content) {
stylesheets = talloc_realloc(c,
c->data.html.stylesheets,
struct nscss_import, i + 1);
if (stylesheets == NULL) {
free(url2);
goto no_memory;
}
c->data.html.stylesheet_content = stylesheet_content;
c->data.html.stylesheet_content[i] = fetchcache(url2,
c->data.html.stylesheets = stylesheets;
/** \todo Reflect actual media specified in link */
c->data.html.stylesheets[i].media = CSS_MEDIA_ALL;
c->data.html.stylesheets[i].c = fetchcache(url2,
html_convert_css_callback,
(intptr_t) c, i, c->width, c->height,
true, 0, 0, false, false);
free(url2);
if (!c->data.html.stylesheet_content[i])
if (c->data.html.stylesheets[i].c == NULL)
goto no_memory;
c->active++;
fetchcache_go(c->data.html.stylesheet_content[i],
fetchcache_go(c->data.html.stylesheets[i].c,
c->url,
html_convert_css_callback,
(intptr_t) c, i, c->width, c->height,
@ -991,7 +995,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *html)
}
/* check that the base stylesheet loaded; layout fails without it */
if (!c->data.html.stylesheet_content[STYLESHEET_BASE]) {
if (c->data.html.stylesheets[STYLESHEET_BASE].c == NULL) {
msg_data.error = "Base stylesheet failed to load";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
@ -1004,10 +1008,10 @@ bool html_find_stylesheets(struct content *c, xmlNode *html)
/* Add sheets to it */
for (i = STYLESHEET_BASE; i != c->data.html.stylesheet_count; i++) {
if (c->data.html.stylesheet_content[i]) {
if (c->data.html.stylesheets[i].c != NULL) {
error = css_select_ctx_append_sheet(
c->data.html.select_ctx,
c->data.html.stylesheet_content[i]->
c->data.html.stylesheets[i].c->
data.css.sheet);
if (error != CSS_OK)
goto no_memory;
@ -1039,7 +1043,7 @@ bool html_process_style_element(struct content *c, unsigned int *index,
xmlNode *child;
char *type, *media, *data;
union content_msg_data msg_data;
struct content **stylesheet_content;
struct nscss_import *stylesheets;
const char *params[] = { 0 };
/* type='text/css', or not present (invalid but common) */
@ -1053,8 +1057,8 @@ bool html_process_style_element(struct content *c, unsigned int *index,
/* media contains 'screen' or 'all' or not present */
if ((media = (char *) xmlGetProp(style, (const xmlChar *) "media"))) {
if (strcasestr(media, "screen") == 0 &&
strcasestr(media, "all") == 0) {
if (strcasestr(media, "screen") == NULL &&
strcasestr(media, "all") == NULL) {
xmlFree(media);
return true;
}
@ -1062,21 +1066,23 @@ bool html_process_style_element(struct content *c, unsigned int *index,
}
/* Extend array */
stylesheet_content = talloc_realloc(c, c->data.html.stylesheet_content,
struct content *, *index + 1);
if (stylesheet_content == NULL)
stylesheets = talloc_realloc(c, c->data.html.stylesheets,
struct nscss_import, *index + 1);
if (stylesheets == NULL)
goto no_memory;
c->data.html.stylesheet_content = stylesheet_content;
c->data.html.stylesheets = stylesheets;
/* create stylesheet */
c->data.html.stylesheet_content[(*index)] =
/** \todo Reflect specified media */
c->data.html.stylesheets[(*index)].media = CSS_MEDIA_ALL;
c->data.html.stylesheets[(*index)].c =
content_create(c->data.html.base_url);
if (c->data.html.stylesheet_content[(*index)] == NULL)
if (c->data.html.stylesheets[(*index)].c == NULL)
goto no_memory;
if (!content_set_type(c->data.html.stylesheet_content[(*index)],
CONTENT_CSS, "text/css", params, c))
if (content_set_type(c->data.html.stylesheets[(*index)].c,
CONTENT_CSS, "text/css", params, c) == false)
/** \todo not necessarily caused by
* memory exhaustion */
goto no_memory;
@ -1086,9 +1092,8 @@ bool html_process_style_element(struct content *c, unsigned int *index,
* the content */
for (child = style->children; child != 0; child = child->next) {
data = (char *) xmlNodeGetContent(child);
if (!content_process_data(c->data.html.
stylesheet_content[(*index)],
data, strlen(data))) {
if (content_process_data(c->data.html.stylesheets[(*index)].c,
data, strlen(data)) == false) {
xmlFree(data);
/** \todo not necessarily caused by
* memory exhaustion */
@ -1098,18 +1103,18 @@ bool html_process_style_element(struct content *c, unsigned int *index,
}
/* Convert the content */
if (nscss_convert(c->data.html.stylesheet_content[(*index)], c->width,
if (nscss_convert(c->data.html.stylesheets[(*index)].c, c->width,
c->height)) {
if (!content_add_user(c->data.html.stylesheet_content[(*index)],
if (content_add_user(c->data.html.stylesheets[(*index)].c,
html_convert_css_callback,
(intptr_t) c, (*index))) {
(intptr_t) c, (*index)) == false) {
/* no memory */
c->data.html.stylesheet_content[(*index)] = NULL;
c->data.html.stylesheets[(*index)].c = NULL;
goto no_memory;
}
} else {
/* conversion failed */
c->data.html.stylesheet_content[(*index)] = NULL;
c->data.html.stylesheets[(*index)].c = NULL;
}
/* Update index */
@ -1135,79 +1140,79 @@ void html_convert_css_callback(content_msg msg, struct content *css,
unsigned int i = p2;
switch (msg) {
case CONTENT_MSG_LOADING:
/* check that the stylesheet is really CSS */
if (css->type != CONTENT_CSS) {
c->data.html.stylesheet_content[i] = 0;
c->active--;
LOG(("%s is not CSS", css->url));
content_add_error(c, "NotCSS", 0);
html_set_status(c, messages_get("NotCSS"));
content_broadcast(c, CONTENT_MSG_STATUS, data);
content_remove_user(css,
html_convert_css_callback,
(intptr_t) c, i);
if (!css->user_list->next) {
/* we were the only user and we
* don't want this content, so
* stop it fetching and mark it
* as having an error so it gets
* removed from the cache next time
* content_clean() gets called */
fetch_abort(css->fetch);
css->fetch = 0;
css->status = CONTENT_STATUS_ERROR;
}
}
break;
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_DONE:
LOG(("got stylesheet '%s'", css->url));
case CONTENT_MSG_LOADING:
/* check that the stylesheet is really CSS */
if (css->type != CONTENT_CSS) {
c->data.html.stylesheets[i].c = NULL;
c->active--;
break;
case CONTENT_MSG_LAUNCH:
/* Fall through */
case CONTENT_MSG_ERROR:
LOG(("stylesheet %s failed: %s", css->url, data.error));
/* The stylesheet we were fetching may have been
* redirected, in that case, the object pointers
* will differ, so ensure that the object that's
* in error is still in use by us before invalidating
* the pointer */
if (c->data.html.stylesheet_content[i] == css) {
c->data.html.stylesheet_content[i] = 0;
c->active--;
content_add_error(c, "?", 0);
}
break;
case CONTENT_MSG_STATUS:
html_set_status(c, css->status_message);
LOG(("%s is not CSS", css->url));
content_add_error(c, "NotCSS", 0);
html_set_status(c, messages_get("NotCSS"));
content_broadcast(c, CONTENT_MSG_STATUS, data);
break;
content_remove_user(css,
html_convert_css_callback,
(intptr_t) c, i);
if (css->user_list->next == NULL) {
/* we were the only user and we
* don't want this content, so
* stop it fetching and mark it
* as having an error so it gets
* removed from the cache next time
* content_clean() gets called */
fetch_abort(css->fetch);
css->fetch = 0;
css->status = CONTENT_STATUS_ERROR;
}
}
break;
case CONTENT_MSG_NEWPTR:
c->data.html.stylesheet_content[i] = css;
break;
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_AUTH:
c->data.html.stylesheet_content[i] = 0;
case CONTENT_MSG_DONE:
LOG(("got stylesheet '%s'", css->url));
c->active--;
break;
case CONTENT_MSG_LAUNCH:
/* Fall through */
case CONTENT_MSG_ERROR:
LOG(("stylesheet %s failed: %s", css->url, data.error));
/* The stylesheet we were fetching may have been
* redirected, in that case, the object pointers
* will differ, so ensure that the object that's
* in error is still in use by us before invalidating
* the pointer */
if (c->data.html.stylesheets[i].c == css) {
c->data.html.stylesheets[i].c = NULL;
c->active--;
content_add_error(c, "?", 0);
break;
}
break;
case CONTENT_MSG_SSL:
c->data.html.stylesheet_content[i] = 0;
c->active--;
content_add_error(c, "?", 0);
break;
case CONTENT_MSG_STATUS:
html_set_status(c, css->status_message);
content_broadcast(c, CONTENT_MSG_STATUS, data);
break;
default:
assert(0);
case CONTENT_MSG_NEWPTR:
c->data.html.stylesheets[i].c = css;
break;
case CONTENT_MSG_AUTH:
c->data.html.stylesheets[i].c = NULL;
c->active--;
content_add_error(c, "?", 0);
break;
case CONTENT_MSG_SSL:
c->data.html.stylesheets[i].c = NULL;
c->active--;
content_add_error(c, "?", 0);
break;
default:
assert(0);
}
}
@ -1811,9 +1816,9 @@ void html_destroy(struct content *c)
/* Free stylesheets */
if (c->data.html.stylesheet_count) {
for (i = 0; i != c->data.html.stylesheet_count; i++) {
if (c->data.html.stylesheet_content[i])
if (c->data.html.stylesheets[i].c)
content_remove_user(c->data.html.
stylesheet_content[i],
stylesheets[i].c,
html_convert_css_callback,
(intptr_t) c, i);
}

View File

@ -136,7 +136,7 @@ struct content_html_data {
/** Number of entries in stylesheet_content. */
unsigned int stylesheet_count;
/** Stylesheets. Each may be 0. */
struct content **stylesheet_content;
struct nscss_import *stylesheets;
/**< Style selection context */
css_select_ctx *select_ctx;