diff --git a/content/content.c b/content/content.c index f5303400d..af4cdaac3 100644 --- a/content/content.c +++ b/content/content.c @@ -186,6 +186,13 @@ nserror content_llcache_callback(llcache_handle *llcache, msg_data.redirect.to = event->data.redirect.to; content_broadcast(c, CONTENT_MSG_REDIRECT, &msg_data); break; + case LLCACHE_EVENT_QUERY: + case LLCACHE_EVENT_QUERY_FINISHED: + /* Should never happen, because the object can't query once + * it has fetched enough that a migration to content happened. + */ + NSLOG(netsurf, DEBUG, "Encountered query related events during content handling"); + break; } return error; diff --git a/content/hlcache.c b/content/hlcache.c index 61cdebe71..c07c5a1a1 100644 --- a/content/hlcache.c +++ b/content/hlcache.c @@ -518,6 +518,20 @@ static nserror hlcache_llcache_callback(llcache_handle *handle, ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw); } break; + case LLCACHE_EVENT_QUERY: + if (hlcache->params.llcache.cb != NULL) { + return hlcache->params.llcache.cb( + event->data.query.query, + hlcache->params.llcache.cb_ctx, + event->data.query.cb, + event->data.query.cb_pw); + } else { + return NSERROR_NOT_IMPLEMENTED; + } + break; + case LLCACHE_EVENT_QUERY_FINISHED: + /* Currently nothing to do */ + break; } return NSERROR_OK; diff --git a/content/llcache.c b/content/llcache.c index 34b43d702..71282f2dd 100644 --- a/content/llcache.c +++ b/content/llcache.c @@ -206,12 +206,6 @@ struct llcache_object { * Core llcache control context. */ struct llcache_s { - /** Handler for fetch-related queries */ - llcache_query_callback query_cb; - - /** Data for fetch-related query handler */ - void *query_cb_pw; - /** Head of the low-level cached object list */ llcache_object *cached_objects; @@ -2267,10 +2261,18 @@ static nserror llcache_query_handle_response(bool proceed, void *cbpw) llcache_event event; llcache_object *object = cbpw; + if (object->fetch.outstanding_query == false) { + /* This object has already had its query answered */ + return NSERROR_OK; + } + object->fetch.outstanding_query = false; + /* Tell all the users that we're leaving query state */ + event.type = LLCACHE_EVENT_QUERY_FINISHED; + /* Refetch, using existing fetch parameters, if client allows us to */ - if (proceed) + if (llcache_send_event_to_users(object, &event) == NSERROR_OK && proceed) return llcache_object_refetch(object); /* Invalidate cache-control data */ @@ -2317,38 +2319,31 @@ static nserror llcache_fetch_auth(llcache_object *object, const char *realm) auth = urldb_get_auth_details(object->url, realm); if (auth == NULL || object->fetch.tried_with_auth == true) { + llcache_query query; + llcache_event event; + /* No authentication details, or tried what we had, so ask */ object->fetch.tried_with_auth = false; - if (llcache->query_cb != NULL) { - llcache_query query; + /* Emit query for authentication details */ + query.type = LLCACHE_QUERY_AUTH; + query.url = object->url; + query.data.auth.realm = realm; - /* Emit query for authentication details */ - query.type = LLCACHE_QUERY_AUTH; - query.url = object->url; - query.data.auth.realm = realm; + /* Construct the query event */ + event.type = LLCACHE_EVENT_QUERY; + event.data.query.query = &query; + event.data.query.cb = llcache_query_handle_response; + event.data.query.cb_pw = object; - object->fetch.outstanding_query = true; + object->fetch.outstanding_query = true; - error = llcache->query_cb(&query, llcache->query_cb_pw, - llcache_query_handle_response, object); - if (error != NSERROR_OK) { - /* do not continue if error querying user */ - error = llcache_query_handle_response(false, - object); - } - } else { - llcache_event event; + error = llcache_send_event_to_users(object, &event); - /* Mark object complete */ - object->fetch.state = LLCACHE_FETCH_COMPLETE; - - /* Inform client(s) that object fetch failed */ - event.type = LLCACHE_EVENT_ERROR; - /** \todo More appropriate error message */ - event.data.msg = messages_get("FetchFailed"); - - error = llcache_send_event_to_users(object, &event); + if (error != NSERROR_OK) { + /* do not continue if error querying user */ + error = llcache_query_handle_response(false, + object); } } else { /* Flag that we've tried to refetch with credentials, so @@ -2383,8 +2378,9 @@ static nserror llcache_fetch_cert_error(llcache_object *object, object->fetch.tainted_tls = true; /* Only give the user a chance if HSTS isn't in use for this fetch */ - if (object->fetch.hsts_in_use == false && llcache->query_cb != NULL) { + if (object->fetch.hsts_in_use == false) { llcache_query query; + llcache_event event; /* Emit query for TLS */ query.type = LLCACHE_QUERY_SSL; @@ -2392,10 +2388,16 @@ static nserror llcache_fetch_cert_error(llcache_object *object, query.data.ssl.certs = certs; query.data.ssl.num = num; + /* Construct the query event */ + event.type = LLCACHE_EVENT_QUERY; + event.data.query.query = &query; + event.data.query.cb = llcache_query_handle_response; + event.data.query.cb_pw = object; + object->fetch.outstanding_query = true; - error = llcache->query_cb(&query, llcache->query_cb_pw, - llcache_query_handle_response, object); + error = llcache_send_event_to_users(object, &event); + if (error != NSERROR_OK) { /* do not continue if error querying user */ error = llcache_query_handle_response(false, object); @@ -3496,8 +3498,6 @@ llcache_initialise(const struct llcache_parameters *prm) return NSERROR_NOMEM; } - llcache->query_cb = prm->cb; - llcache->query_cb_pw = prm->cb_ctx; llcache->limit = prm->limit; llcache->minimum_lifetime = prm->minimum_lifetime; llcache->minimum_bandwidth = prm->minimum_bandwidth; diff --git a/content/llcache.h b/content/llcache.h index 796db66f8..762edf060 100644 --- a/content/llcache.h +++ b/content/llcache.h @@ -48,45 +48,6 @@ typedef struct llcache_post_data { } data; /**< POST data content */ } llcache_post_data; -/** Low-level cache event types */ -typedef enum { - LLCACHE_EVENT_HAD_HEADERS, /**< Received all headers */ - LLCACHE_EVENT_HAD_DATA, /**< Received some data */ - LLCACHE_EVENT_DONE, /**< Finished fetching data */ - - LLCACHE_EVENT_ERROR, /**< An error occurred during fetch */ - LLCACHE_EVENT_PROGRESS, /**< Fetch progress update */ - - LLCACHE_EVENT_REDIRECT /**< Fetch URL redirect occured */ -} llcache_event_type; - -/** Low-level cache events */ -typedef struct { - llcache_event_type type; /**< Type of event */ - union { - struct { - const uint8_t *buf; /**< Buffer of data */ - size_t len; /**< Length of buffer, in bytes */ - } data; /**< Received data */ - const char *msg; /**< Error or progress message */ - struct { - nsurl *from; /**< Redirect origin */ - nsurl *to; /**< Redirect target */ - } redirect; /**< Fetch URL redirect occured */ - } data; /**< Event data */ -} llcache_event; - -/** - * Client callback for low-level cache events - * - * \param handle Handle for which event is issued - * \param event Event data - * \param pw Pointer to client-specific data - * \return NSERROR_OK on success, appropriate error otherwise. - */ -typedef nserror (*llcache_handle_callback)(llcache_handle *handle, - const llcache_event *event, void *pw); - /** Flags for low-level cache object retrieval */ enum llcache_retrieve_flag { /* Note: We're permitted a maximum of 16 flags which must reside in the @@ -140,6 +101,58 @@ typedef struct { */ typedef nserror (*llcache_query_response)(bool proceed, void *cbpw); +/** Low-level cache event types */ +typedef enum { + LLCACHE_EVENT_HAD_HEADERS, /**< Received all headers */ + LLCACHE_EVENT_HAD_DATA, /**< Received some data */ + LLCACHE_EVENT_DONE, /**< Finished fetching data */ + + LLCACHE_EVENT_ERROR, /**< An error occurred during fetch */ + LLCACHE_EVENT_PROGRESS, /**< Fetch progress update */ + + LLCACHE_EVENT_QUERY, /**< Fetch has a query and is paused */ + LLCACHE_EVENT_QUERY_FINISHED, /**< Fetch had a query, but it is now finished */ + + LLCACHE_EVENT_REDIRECT /**< Fetch URL redirect occured */ +} llcache_event_type; + +/** + * Low-level cache events. + * + * Lifetime of contained information is only for the duration of the event + * and must be copied if it is desirable to retain. + */ +typedef struct { + llcache_event_type type; /**< Type of event */ + union { + struct { + const uint8_t *buf; /**< Buffer of data */ + size_t len; /**< Length of buffer, in bytes */ + } data; /**< Received data */ + const char *msg; /**< Error or progress message */ + struct { + nsurl *from; /**< Redirect origin */ + nsurl *to; /**< Redirect target */ + } redirect; /**< Fetch URL redirect occured */ + struct { + llcache_query *query; /**< Query information */ + llcache_query_response cb; /**< Response callback */ + void *cb_pw; /**< Response callback private word */ + } query; /**< Query event */ + } data; /**< Event data */ +} llcache_event; + +/** + * Client callback for low-level cache events + * + * \param handle Handle for which event is issued + * \param event Event data + * \param pw Pointer to client-specific data + * \return NSERROR_OK on success, appropriate error otherwise. + */ +typedef nserror (*llcache_handle_callback)(llcache_handle *handle, + const llcache_event *event, void *pw); + /** * Callback to handle fetch-related queries * diff --git a/desktop/download.c b/desktop/download.c index 76c294977..da229491d 100644 --- a/desktop/download.c +++ b/desktop/download.c @@ -234,6 +234,13 @@ static nserror download_callback(llcache_handle *handle, case LLCACHE_EVENT_REDIRECT: break; + case LLCACHE_EVENT_QUERY: + case LLCACHE_EVENT_QUERY_FINISHED: + /* It's *POSSIBLE* we might have to handle these here + * but how? + */ + NSLOG(netsurf, DEBUG, "Encountered query related events during download handling"); + return NSERROR_NOT_IMPLEMENTED; } return error;