mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-24 23:39:51 +03:00
add internal query handler for fetch errors
Any errors from the fetch which are not already handled are reported with an internal query page instead of a modal dialog. This is much less invasive for the user and much more in keeping with how this is handled by other browsers. The handler is similar to the timeout handler but the functionality is kept separate as it is intended timeout handling be extended in future.
This commit is contained in:
parent
76eac19227
commit
4b0c3f0efe
@ -94,6 +94,11 @@ static const char *privacy_description_fallback = "A privacy error occurred whil
|
||||
*/
|
||||
static const char *timeout_description_fallback = "A connection to %s could not be established. The site may be temporarily unavailable or too busy to respond.";
|
||||
|
||||
/**
|
||||
* fetcherror query description if messages fails to retrieve usable text
|
||||
*/
|
||||
static const char *fetcherror_description_fallback = "An error occoured when connecting to %s";
|
||||
|
||||
/**
|
||||
* issue fetch callbacks with locking
|
||||
*/
|
||||
@ -1239,6 +1244,130 @@ fetch_about_query_timeout_handler_aborted:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler to generate about scheme fetch error query page
|
||||
*
|
||||
* \param ctx The fetcher context.
|
||||
* \return true if handled false if aborted.
|
||||
*/
|
||||
static bool
|
||||
fetch_about_query_fetcherror_handler(struct fetch_about_context *ctx)
|
||||
{
|
||||
nserror res;
|
||||
char *url_s;
|
||||
size_t url_l;
|
||||
const char *reason = "";
|
||||
const char *title;
|
||||
struct nsurl *siteurl = NULL;
|
||||
char *description = NULL;
|
||||
const struct fetch_multipart_data *curmd; /* mutipart data iterator */
|
||||
|
||||
/* extract parameters from multipart post data */
|
||||
curmd = ctx->multipart;
|
||||
while (curmd != NULL) {
|
||||
if (strcmp(curmd->name, "siteurl") == 0) {
|
||||
res = nsurl_create(curmd->value, &siteurl);
|
||||
if (res != NSERROR_OK) {
|
||||
return fetch_about_srverror(ctx);
|
||||
}
|
||||
} else if (strcmp(curmd->name, "reason") == 0) {
|
||||
reason = curmd->value;
|
||||
}
|
||||
curmd = curmd->next;
|
||||
}
|
||||
|
||||
if (siteurl == NULL) {
|
||||
return fetch_about_srverror(ctx);
|
||||
}
|
||||
|
||||
/* content is going to return ok */
|
||||
fetch_set_http_code(ctx->fetchh, 200);
|
||||
|
||||
/* content type */
|
||||
if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
|
||||
goto fetch_about_query_fetcherror_handler_aborted;
|
||||
}
|
||||
|
||||
title = messages_get("FetchErrorTitle");
|
||||
res = ssenddataf(ctx,
|
||||
"<html>\n<head>\n"
|
||||
"<title>%s</title>\n"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" "
|
||||
"href=\"resource:internal.css\">\n"
|
||||
"</head>\n"
|
||||
"<body id =\"fetcherror\">\n"
|
||||
"<h1>%s</h1>\n",
|
||||
title, title);
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_fetcherror_handler_aborted;
|
||||
}
|
||||
|
||||
res = ssenddataf(ctx,
|
||||
"<form method=\"post\""
|
||||
" enctype=\"multipart/form-data\">");
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_fetcherror_handler_aborted;
|
||||
}
|
||||
|
||||
res = get_query_description(siteurl,
|
||||
"FetchErrorDescription",
|
||||
fetcherror_description_fallback,
|
||||
&description);
|
||||
if (res == NSERROR_OK) {
|
||||
res = ssenddataf(ctx, "<div><p>%s</p></div>", description);
|
||||
free(description);
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_fetcherror_handler_aborted;
|
||||
}
|
||||
}
|
||||
res = ssenddataf(ctx, "<div><p>%s</p></div>", reason);
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_fetcherror_handler_aborted;
|
||||
}
|
||||
|
||||
res = ssenddataf(ctx,
|
||||
"<div id=\"buttons\">"
|
||||
"<input type=\"submit\" id=\"back\" name=\"back\" "
|
||||
"value=\"%s\" class=\"default-action\">"
|
||||
"<input type=\"submit\" id=\"retry\" name=\"retry\" "
|
||||
"value=\"%s\">"
|
||||
"</div>",
|
||||
messages_get("Backtoprevious"),
|
||||
messages_get("TryAgain"));
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_fetcherror_handler_aborted;
|
||||
}
|
||||
|
||||
res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
|
||||
if (res != NSERROR_OK) {
|
||||
url_s = strdup("");
|
||||
}
|
||||
res = ssenddataf(ctx,
|
||||
"<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
|
||||
url_s);
|
||||
free(url_s);
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_fetcherror_handler_aborted;
|
||||
}
|
||||
|
||||
res = ssenddataf(ctx, "</form></body>\n</html>\n");
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_fetcherror_handler_aborted;
|
||||
}
|
||||
|
||||
fetch_about_send_finished(ctx);
|
||||
|
||||
nsurl_unref(siteurl);
|
||||
|
||||
return true;
|
||||
|
||||
fetch_about_query_fetcherror_handler_aborted:
|
||||
nsurl_unref(siteurl);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Forward declaration because this handler requires the handler table. */
|
||||
static bool fetch_about_about_handler(struct fetch_about_context *ctx);
|
||||
|
||||
@ -1352,6 +1481,13 @@ struct about_handlers about_handler_list[] = {
|
||||
NULL,
|
||||
fetch_about_query_timeout_handler,
|
||||
true
|
||||
},
|
||||
{
|
||||
"query/fetcherror",
|
||||
SLEN("query/fetcherror"),
|
||||
NULL,
|
||||
fetch_about_query_fetcherror_handler,
|
||||
true
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1216,6 +1216,50 @@ browser_window__handle_timeout(struct browser_window *bw, nsurl *url)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle non specific errors during a fetch
|
||||
*/
|
||||
static nserror
|
||||
browser_window__handle_fetcherror(struct browser_window *bw,
|
||||
const char *reason,
|
||||
nsurl *url)
|
||||
{
|
||||
struct browser_fetch_parameters params;
|
||||
nserror err;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
params.url = nsurl_ref(corestring_nsurl_about_query_fetcherror);
|
||||
params.referrer = nsurl_ref(url);
|
||||
params.flags = BW_NAVIGATE_HISTORY | BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE | BW_NAVIGATE_INTERNAL;
|
||||
|
||||
err = fetch_multipart_data_new_kv(¶ms.post_multipart,
|
||||
"siteurl",
|
||||
nsurl_access(url));
|
||||
if (err != NSERROR_OK) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = fetch_multipart_data_new_kv(¶ms.post_multipart,
|
||||
"reason",
|
||||
reason);
|
||||
if (err != NSERROR_OK) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Now we issue the fetch */
|
||||
bw->internal_nav = true;
|
||||
err = browser_window__navigate_internal(bw, ¶ms);
|
||||
if (err != NSERROR_OK) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
browser_window__free_fetch_parameters(¶ms);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle errors during content fetch
|
||||
*/
|
||||
@ -1226,40 +1270,15 @@ browser_window__handle_error(struct browser_window *bw,
|
||||
{
|
||||
const char *message = event->data.errordata.errormsg;
|
||||
nserror code = event->data.errordata.errorcode;
|
||||
bool do_warning = true;
|
||||
nserror res;
|
||||
nsurl *url = hlcache_handle_get_url(c);
|
||||
|
||||
/* Unexpected OK? */
|
||||
assert(code != NSERROR_OK);
|
||||
|
||||
switch (code) {
|
||||
case NSERROR_BAD_AUTH:
|
||||
do_warning = false;
|
||||
break;
|
||||
case NSERROR_BAD_CERTS:
|
||||
do_warning = false;
|
||||
break;
|
||||
case NSERROR_BAD_REDIRECT:
|
||||
/* The message is already filled out */
|
||||
break;
|
||||
case NSERROR_TIMEOUT:
|
||||
do_warning = false;
|
||||
break;
|
||||
default:
|
||||
if (message == NULL) {
|
||||
message = messages_get_errorcode(code);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (do_warning) {
|
||||
browser_window_set_status(bw, message);
|
||||
/* Only warn the user about errors in top-level windows */
|
||||
if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) {
|
||||
guit->misc->warning(message, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (c == bw->loading_content) {
|
||||
bw->loading_content = NULL;
|
||||
@ -1274,13 +1293,17 @@ browser_window__handle_error(struct browser_window *bw,
|
||||
case NSERROR_BAD_AUTH:
|
||||
res = browser_window__handle_login(bw, message, url);
|
||||
break;
|
||||
|
||||
case NSERROR_BAD_CERTS:
|
||||
res = browser_window__handle_bad_certs(bw, url);
|
||||
break;
|
||||
|
||||
case NSERROR_TIMEOUT:
|
||||
res = browser_window__handle_timeout(bw, url);
|
||||
break;
|
||||
|
||||
default:
|
||||
res = browser_window__handle_fetcherror(bw, message, url);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2411,6 +2434,8 @@ is_internal_navigate_url(nsurl *url)
|
||||
is_internal = true;
|
||||
} else if (path == corestring_lwc_query_timeout) {
|
||||
is_internal = true;
|
||||
} else if (path == corestring_lwc_query_fetcherror) {
|
||||
is_internal = true;
|
||||
}
|
||||
}
|
||||
lwc_string_unref(path);
|
||||
@ -3613,6 +3638,42 @@ navigate_internal_query_timeout(struct browser_window *bw,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal navigation handler for the fetch error query page.
|
||||
*
|
||||
* If the parameters indicate we're processing a *response* from the handler
|
||||
* then we deal with that, otherwise we pass it on to the about: handler
|
||||
*/
|
||||
static nserror
|
||||
navigate_internal_query_fetcherror(struct browser_window *bw,
|
||||
struct browser_fetch_parameters *params)
|
||||
{
|
||||
bool is_retry = false, is_back = false;
|
||||
|
||||
NSLOG(netsurf, INFO, "bw:%p params:%p", bw, params);
|
||||
|
||||
assert(params->post_multipart != NULL);
|
||||
|
||||
is_retry = fetch_multipart_data_find(params->post_multipart, "retry") != NULL;
|
||||
is_back = fetch_multipart_data_find(params->post_multipart, "back") != NULL;
|
||||
|
||||
if (is_back) {
|
||||
/* do a rough-and-ready nav to the old 'current'
|
||||
* parameters, with any post data stripped away
|
||||
*/
|
||||
return browser_window__reload_current_parameters(bw);
|
||||
}
|
||||
|
||||
if (is_retry) {
|
||||
/* Finally navigate to the original loading parameters */
|
||||
bw->internal_nav = false;
|
||||
return navigate_internal_real(bw, &bw->loading_parameters);
|
||||
}
|
||||
|
||||
return navigate_internal_real(bw, params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dispatch to internal query handlers or normal navigation
|
||||
*
|
||||
@ -3651,6 +3712,10 @@ browser_window__navigate_internal(struct browser_window *bw,
|
||||
lwc_string_unref(path);
|
||||
return navigate_internal_query_timeout(bw, params);
|
||||
}
|
||||
if (path == corestring_lwc_query_fetcherror) {
|
||||
lwc_string_unref(path);
|
||||
return navigate_internal_query_fetcherror(bw, params);
|
||||
}
|
||||
lwc_string_unref(path);
|
||||
|
||||
/* Fall through to a normal about: fetch */
|
||||
|
@ -1096,6 +1096,13 @@ en.all.Backtoprevious: Back
|
||||
en.all.TryAgain: Try Again
|
||||
|
||||
|
||||
# Fetch error interface
|
||||
# =======================
|
||||
#
|
||||
en.all.FetchErrorTitle:Error occured fetching page
|
||||
en.all.FetchErrorDescription:An error occoured when connecting to %s
|
||||
|
||||
|
||||
# SSL certificate viewer
|
||||
# ======================
|
||||
#
|
||||
|
@ -381,3 +381,41 @@ body#timeout div#buttons {
|
||||
body#timeout div#buttons input#back {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
/*
|
||||
* fetch error query styling
|
||||
*/
|
||||
|
||||
body#fetcherror {
|
||||
max-width: 45em;
|
||||
}
|
||||
|
||||
body#fetcherror h1 {
|
||||
padding: 0.8em 0.4em 0.5em 0.4em;
|
||||
border-bottom: 0.1em solid #444;
|
||||
margin: 0 0 1.3em 0;
|
||||
background: #c55;
|
||||
color: white;
|
||||
}
|
||||
|
||||
body#fetcherror form {
|
||||
/* Just to center the form on the page */
|
||||
margin: 0 auto;
|
||||
/* To see the outline of the form */
|
||||
padding: 1em;
|
||||
border: 1px solid #CCC;
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
body#fetcherror form div + div {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
body#fetcherror div#buttons {
|
||||
text-align: right;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
body#fetcherror div#buttons input#back {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ CORESTRING_LWC_VALUE(no_store, "no-store");
|
||||
CORESTRING_LWC_VALUE(query_auth, "query/auth");
|
||||
CORESTRING_LWC_VALUE(query_ssl, "query/ssl");
|
||||
CORESTRING_LWC_VALUE(query_timeout, "query/timeout");
|
||||
CORESTRING_LWC_VALUE(query_fetcherror, "query/fetcherror");
|
||||
|
||||
/* mime types */
|
||||
CORESTRING_LWC_VALUE(multipart_form_data, "multipart/form-data");
|
||||
@ -362,6 +363,7 @@ CORESTRING_NSURL(about_blank, "about:blank");
|
||||
CORESTRING_NSURL(about_query_ssl, "about:query/ssl");
|
||||
CORESTRING_NSURL(about_query_auth, "about:query/auth");
|
||||
CORESTRING_NSURL(about_query_timeout, "about:query/timeout");
|
||||
CORESTRING_NSURL(about_query_fetcherror, "about:query/fetcherror");
|
||||
|
||||
#undef CORESTRING_LWC_STRING
|
||||
#undef CORESTRING_DOM_STRING
|
||||
|
Loading…
Reference in New Issue
Block a user