NetSurf
hlcache.c
Go to the documentation of this file.
1/*
2 * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * High-level resource cache implementation.
22 */
23
24#include <assert.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "utils/http.h"
29#include "utils/log.h"
30#include "utils/messages.h"
31#include "utils/ring.h"
32#include "utils/utils.h"
33#include "netsurf/inttypes.h"
34#include "netsurf/misc.h"
35#include "netsurf/content.h"
37
38#include "content/mimesniff.h"
39#include "content/hlcache.h"
40// Note, this is *ONLY* so that we can abort cleanly during shutdown of the cache
43
46
47/** High-level cache retrieval context */
49 struct hlcache_retrieval_ctx *r_prev; /**< Previous retrieval context in the ring */
50 struct hlcache_retrieval_ctx *r_next; /**< Next retrieval context in the ring */
51
52 llcache_handle *llcache; /**< Low-level cache handle */
53
54 hlcache_handle *handle; /**< High-level handle for object */
55
56 uint32_t flags; /**< Retrieval flags */
57
58 content_type accepted_types; /**< Accepted types */
59
60 hlcache_child_context child; /**< Child context */
61
62 bool migrate_target; /**< Whether this context is the migration target */
63};
64
65/** High-level cache handle */
67 hlcache_entry *entry; /**< Pointer to cache entry */
68
69 hlcache_handle_callback cb; /**< Client callback */
70 void *pw; /**< Client data */
71};
72
73/** Entry in high-level cache */
75 struct content *content; /**< Pointer to associated content */
76
77 hlcache_entry *next; /**< Next sibling */
78 hlcache_entry *prev; /**< Previous sibling */
79};
80
81/** Current state of the cache.
82 *
83 * Global state of the cache.
84 */
85struct hlcache_s {
87
88 /** List of cached content objects */
90
91 /** Ring of retrieval contexts */
93
94 /* statistics */
95 unsigned int hit_count;
96 unsigned int miss_count;
97};
98
99/** high level cache state */
100static struct hlcache_s *hlcache = NULL;
101
102
103/******************************************************************************
104 * High-level cache internals *
105 ******************************************************************************/
106
107
108/**
109 * Attempt to clean the cache
110 */
111static void hlcache_clean(void *force_clean_flag)
112{
113 hlcache_entry *entry, *next;
114 bool force_clean = (force_clean_flag != NULL);
115
116 for (entry = hlcache->content_list; entry != NULL; entry = next) {
117 next = entry->next;
118
119 if (entry->content == NULL)
120 continue;
121
122 if (content_count_users(entry->content) != 0)
123 continue;
124
126 if (force_clean == false)
127 continue;
128 NSLOG(netsurf, DEBUG, "Forcing content cleanup during shutdown");
129 content_abort(entry->content);
131 }
132
133 /** \todo This is over-zealous: all unused contents
134 * will be immediately destroyed. Ideally, we want to
135 * purge all unused contents that are using stale
136 * source data, and enough fresh contents such that
137 * the cache fits in the configured cache size limit.
138 */
139
140 /* Remove entry from cache */
141 if (entry->prev == NULL)
142 hlcache->content_list = entry->next;
143 else
144 entry->prev->next = entry->next;
145
146 if (entry->next != NULL)
147 entry->next->prev = entry->prev;
148
149 /* Destroy content */
150 content_destroy(entry->content);
151
152 /* Destroy entry */
153 free(entry);
154 }
155
156 /* Attempt to clean the llcache */
157 llcache_clean(false);
158
159 /* Re-schedule ourselves */
161}
162
163/**
164 * Determine if the specified MIME type is acceptable
165 *
166 * \param mime_type MIME type to consider
167 * \param accepted_types Array of acceptable types, or NULL for any
168 * \param computed_type Pointer to location to receive computed type of object
169 * \return True if the type is acceptable, false otherwise
170 */
171static bool hlcache_type_is_acceptable(lwc_string *mime_type,
172 content_type accepted_types, content_type *computed_type)
173{
175
177
178 *computed_type = type;
179
180 return ((accepted_types & type) != 0);
181}
182
183/**
184 * Veneer between content callback API and hlcache callback API
185 *
186 * \param c Content to emit message for
187 * \param msg Message to emit
188 * \param data Data for message
189 * \param pw Pointer to private data (hlcache_handle)
190 */
192 const union content_msg_data *data, void *pw)
193{
194 hlcache_handle *handle = pw;
195 nserror error = NSERROR_OK;
196 hlcache_event event = {
197 .type = msg,
198 };
199
200 if (data != NULL) {
201 event.data = *data;
202 }
203
204 if (handle->cb != NULL)
205 error = handle->cb(handle, &event, handle->pw);
206
207 if (error != NSERROR_OK)
208 NSLOG(netsurf, INFO, "Error in callback: %d", error);
209}
210
211/**
212 * Find a content for the high-level cache handle
213 *
214 * \param ctx High-level cache retrieval context
215 * \param effective_type Effective MIME type of content
216 * \return NSERROR_OK on success,
217 * NSERROR_NEED_DATA on success where data is needed,
218 * appropriate error otherwise
219 *
220 * \pre handle::state == HLCACHE_HANDLE_NEW
221 * \pre Headers must have been received for associated low-level handle
222 * \post Low-level handle is either released, or associated with new content
223 * \post High-level handle is registered with content
224 */
226 lwc_string *effective_type)
227{
228 hlcache_entry *entry;
229 hlcache_event event;
230 nserror error = NSERROR_OK;
231
232 /* Search list of cached contents for a suitable one */
233 for (entry = hlcache->content_list; entry != NULL; entry = entry->next) {
234 hlcache_handle entry_handle = { entry, NULL, NULL };
235 const llcache_handle *entry_llcache;
236
237 if (entry->content == NULL)
238 continue;
239
240 /* Ignore contents in the error state */
241 if (content_get_status(&entry_handle) == CONTENT_STATUS_ERROR)
242 continue;
243
244 /* Ensure that content is shareable */
245 if (content_is_shareable(entry->content) == false)
246 continue;
247
248 /* Ensure that quirks mode is acceptable */
250 ctx->child.quirks) == false)
251 continue;
252
253 /* Ensure that content uses same low-level object as
254 * low-level handle */
255 entry_llcache = content_get_llcache_handle(entry->content);
256
258 ctx->llcache))
259 break;
260 }
261
262 if (entry == NULL) {
263 /* No existing entry, so need to create one */
264 entry = malloc(sizeof(hlcache_entry));
265 if (entry == NULL)
266 return NSERROR_NOMEM;
267
268 /* Create content using llhandle */
270 ctx->child.charset, ctx->child.quirks,
271 effective_type);
272 if (entry->content == NULL) {
273 free(entry);
274 return NSERROR_NOMEM;
275 }
276
277 /* Insert into cache */
278 entry->prev = NULL;
279 entry->next = hlcache->content_list;
280 if (hlcache->content_list != NULL)
281 hlcache->content_list->prev = entry;
282 hlcache->content_list = entry;
283
284 /* Signal to caller that we created a content */
285 error = NSERROR_NEED_DATA;
286
288 } else {
289 /* Found a suitable content: no longer need low-level handle */
292 }
293
294 /* Associate handle with content */
295 if (content_add_user(entry->content,
296 hlcache_content_callback, ctx->handle) == false)
297 return NSERROR_NOMEM;
298
299 /* Associate cache entry with handle */
300 ctx->handle->entry = entry;
301
302 /* Catch handle up with state of content */
303 if (ctx->handle->cb != NULL) {
305
306 if (status == CONTENT_STATUS_LOADING) {
307 event.type = CONTENT_MSG_LOADING;
308 ctx->handle->cb(ctx->handle, &event, ctx->handle->pw);
309 } else if (status == CONTENT_STATUS_READY) {
310 event.type = CONTENT_MSG_LOADING;
311 ctx->handle->cb(ctx->handle, &event, ctx->handle->pw);
312
313 if (ctx->handle->cb != NULL) {
314 event.type = CONTENT_MSG_READY;
315 ctx->handle->cb(ctx->handle, &event,
316 ctx->handle->pw);
317 }
318 } else if (status == CONTENT_STATUS_DONE) {
319 event.type = CONTENT_MSG_LOADING;
320 ctx->handle->cb(ctx->handle, &event, ctx->handle->pw);
321
322 if (ctx->handle->cb != NULL) {
323 event.type = CONTENT_MSG_READY;
324 ctx->handle->cb(ctx->handle, &event,
325 ctx->handle->pw);
326 }
327
328 if (ctx->handle->cb != NULL) {
329 event.type = CONTENT_MSG_DONE;
330 ctx->handle->cb(ctx->handle, &event,
331 ctx->handle->pw);
332 }
333 }
334 }
335
336 return error;
337}
338
339/**
340 * Migrate a retrieval context into its final destination content
341 *
342 * \param ctx Context to migrate
343 * \param effective_type The effective MIME type of the content, or NULL
344 * \return NSERROR_OK on success,
345 * NSERROR_NEED_DATA on success where data is needed,
346 * appropriate error otherwise
347 */
349 lwc_string *effective_type)
350{
352 nserror error = NSERROR_OK;
353
354 ctx->migrate_target = true;
355
356 if ((effective_type != NULL) &&
357 hlcache_type_is_acceptable(effective_type,
358 ctx->accepted_types,
359 &type)) {
360 error = hlcache_find_content(ctx, effective_type);
361 if (error != NSERROR_OK && error != NSERROR_NEED_DATA) {
362 if (ctx->handle->cb != NULL) {
363 hlcache_event hlevent;
364
365 hlevent.type = CONTENT_MSG_ERROR;
367 hlevent.data.errordata.errormsg = messages_get("MiscError");
368
369 ctx->handle->cb(ctx->handle, &hlevent,
370 ctx->handle->pw);
371 }
372
375 }
376 } else if (type == CONTENT_NONE &&
378 /* Unknown type, and we can download, so convert */
380
381 if (ctx->handle->cb != NULL) {
382 hlcache_event hlevent;
383
384 hlevent.type = CONTENT_MSG_DOWNLOAD;
385 hlevent.data.download = ctx->llcache;
386
387 ctx->handle->cb(ctx->handle, &hlevent,
388 ctx->handle->pw);
389 }
390
391 /* Ensure caller knows we need data */
392 error = NSERROR_NEED_DATA;
393 } else {
394 /* Unacceptable type: report error */
395 if (ctx->handle->cb != NULL) {
396 hlcache_event hlevent;
397
398 hlevent.type = CONTENT_MSG_ERROR;
400 hlevent.data.errordata.errormsg = messages_get("UnacceptableType");
401
402 ctx->handle->cb(ctx->handle, &hlevent,
403 ctx->handle->pw);
404 }
405
408 }
409
410 ctx->migrate_target = false;
411
412 /* No longer require retrieval context */
414 free((char *) ctx->child.charset);
415 free(ctx);
416
417 return error;
418}
419
420/**
421 * Handler for low-level cache events
422 *
423 * \param handle Handle for which event is issued
424 * \param event Event data
425 * \param pw Pointer to client-specific data
426 * \return NSERROR_OK on success, appropriate error otherwise
427 */
428static nserror
430 const llcache_event *event,
431 void *pw)
432{
433 hlcache_retrieval_ctx *ctx = pw;
434 lwc_string *effective_type = NULL;
435 nserror error;
436
437 assert(ctx->llcache == handle);
438
439 switch (event->type) {
441 /* Pass them on upward */
442 if (ctx->handle->cb != NULL) {
443 hlcache_event hlevent;
444
445 hlevent.type = CONTENT_MSG_SSL_CERTS;
446 hlevent.data.chain = event->data.chain;
447
448 ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw);
449 }
450 break;
452 error = mimesniff_compute_effective_type(llcache_handle_get_header(handle, "Content-Type"), NULL, 0,
455 &effective_type);
456 if (error == NSERROR_OK || error == NSERROR_NOT_FOUND) {
457 /* If the sniffer was successful or failed to find
458 * a Content-Type header when sniffing was
459 * prohibited, we must migrate the retrieval context. */
460 error = hlcache_migrate_ctx(ctx, effective_type);
461
462 if (effective_type != NULL)
463 lwc_string_unref(effective_type);
464 }
465
466 /* No need to report that we need data:
467 * we'll get some anyway if there is any */
468 if (error == NSERROR_NEED_DATA)
469 error = NSERROR_OK;
470
471 return error;
472
473 break;
475 error = mimesniff_compute_effective_type(llcache_handle_get_header(handle, "Content-Type"),
476 event->data.data.buf, event->data.data.len,
479 &effective_type);
480 if (error != NSERROR_OK) {
481 assert(0 && "MIME sniff failed with data");
482 }
483
484 error = hlcache_migrate_ctx(ctx, effective_type);
485
486 lwc_string_unref(effective_type);
487
488 return error;
489
490 break;
492 /* DONE event before we could determine the effective MIME type.
493 */
494 error = mimesniff_compute_effective_type(llcache_handle_get_header(handle, "Content-Type"),
495 NULL, 0, false, false, &effective_type);
496 if (error == NSERROR_OK || error == NSERROR_NOT_FOUND) {
497 error = hlcache_migrate_ctx(ctx, effective_type);
498
499 if (effective_type != NULL) {
500 lwc_string_unref(effective_type);
501 }
502
503 return error;
504 }
505
506 if (ctx->handle->cb != NULL) {
507 hlcache_event hlevent;
508
509 hlevent.type = CONTENT_MSG_ERROR;
510 hlevent.data.errordata.errorcode = error;
511 hlevent.data.errordata.errormsg = NULL;
512
513 ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw);
514 }
515 break;
517 if (ctx->handle->cb != NULL) {
518 hlcache_event hlevent;
519
520 hlevent.type = CONTENT_MSG_ERROR;
521 hlevent.data.errordata.errorcode = event->data.error.code;
522 hlevent.data.errordata.errormsg = event->data.error.msg;
523
524 ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw);
525 }
526 break;
528 break;
530 if (ctx->handle->cb != NULL) {
531 hlcache_event hlevent;
532
533 hlevent.type = CONTENT_MSG_REDIRECT;
534 hlevent.data.redirect.from = event->data.redirect.from;
535 hlevent.data.redirect.to = event->data.redirect.to;
536
537 ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw);
538 }
539 break;
540 }
541
542 return NSERROR_OK;
543}
544
545
546/******************************************************************************
547 * Public API *
548 ******************************************************************************/
549
550
553{
554 nserror ret;
555
556 hlcache = calloc(1, sizeof(struct hlcache_s));
557 if (hlcache == NULL) {
558 return NSERROR_NOMEM;
559 }
560
562 if (ret != NSERROR_OK) {
563 free(hlcache);
564 hlcache = NULL;
565 return ret;
566 }
567
569
570 /* Schedule the cache cleanup */
572
573 return NSERROR_OK;
574}
575
576/* See hlcache.h for documentation */
577void hlcache_stop(void)
578{
579 /* Remove the hlcache_clean schedule */
580 guit->misc->schedule(-1, hlcache_clean, NULL);
581}
582
583/* See hlcache.h for documentation */
585{
586 uint32_t num_contents, prev_contents;
587 hlcache_entry *entry;
588 hlcache_retrieval_ctx *ctx, *next;
589
590 /* Obtain initial count of contents remaining */
591 for (num_contents = 0, entry = hlcache->content_list;
592 entry != NULL; entry = entry->next) {
593 num_contents++;
594 }
595
596 NSLOG(netsurf, INFO, "%"PRIu32" contents remain before cache drain",
597 num_contents);
598
599 /* Drain cache */
600 do {
601 prev_contents = num_contents;
602
603 hlcache_clean(NULL);
604
605 for (num_contents = 0, entry = hlcache->content_list;
606 entry != NULL; entry = entry->next) {
607 num_contents++;
608 }
609 } while (num_contents > 0 && num_contents != prev_contents);
610
611 NSLOG(netsurf, INFO, "%"PRIu32" contents remaining after being polite",
612 num_contents);
613
614 /* Drain cache again, forcing the matter */
615 do {
616 prev_contents = num_contents;
617
618 hlcache_clean(&entry); // Any non-NULL pointer will do
619
620 for (num_contents = 0, entry = hlcache->content_list;
621 entry != NULL; entry = entry->next) {
622 num_contents++;
623 }
624 } while (num_contents > 0 && num_contents != prev_contents);
625
626 NSLOG(netsurf, INFO, "%"PRIu32" contents remaining:", num_contents);
627 for (entry = hlcache->content_list; entry != NULL; entry = entry->next) {
628 hlcache_handle entry_handle = { entry, NULL, NULL };
629
630 if (entry->content != NULL) {
631 NSLOG(netsurf, INFO, " %p : %s (%"PRIu32" users)",
632 entry,
633 nsurl_access(hlcache_handle_get_url(&entry_handle)),
635 } else {
636 NSLOG(netsurf, INFO, " %p", entry);
637 }
638 }
639
640 /* Clean up retrieval contexts */
641 if (hlcache->retrieval_ctx_ring != NULL) {
643
644 do {
645 next = ctx->r_next;
646
647 if (ctx->llcache != NULL)
649
650 if (ctx->handle != NULL)
651 free(ctx->handle);
652
653 if (ctx->child.charset != NULL)
654 free((char *) ctx->child.charset);
655
656 free(ctx);
657
658 ctx = next;
659 } while (ctx != hlcache->retrieval_ctx_ring);
660
662 }
663
664 NSLOG(netsurf, INFO, "hit/miss %d/%d", hlcache->hit_count,
666
667 /* De-schedule ourselves */
668 guit->misc->schedule(-1, hlcache_clean, NULL);
669
670 free(hlcache);
671 hlcache = NULL;
672
673 NSLOG(netsurf, INFO, "Finalising low-level cache");
675}
676
677/* See hlcache.h for documentation */
680 uint32_t flags,
681 nsurl *referer,
682 llcache_post_data *post,
683 hlcache_handle_callback cb, void *pw,
685 content_type accepted_types,
687{
689 nserror error;
690
691 assert(cb != NULL);
692
693 ctx = calloc(1, sizeof(hlcache_retrieval_ctx));
694 if (ctx == NULL) {
695 return NSERROR_NOMEM;
696 }
697
698 ctx->handle = calloc(1, sizeof(hlcache_handle));
699 if (ctx->handle == NULL) {
700 free(ctx);
701 return NSERROR_NOMEM;
702 }
703
704 if (child != NULL) {
705 if (child->charset != NULL) {
706 ctx->child.charset = strdup(child->charset);
707 if (ctx->child.charset == NULL) {
708 free(ctx->handle);
709 free(ctx);
710 return NSERROR_NOMEM;
711 }
712 }
713 ctx->child.quirks = child->quirks;
714 }
715
716 ctx->flags = flags;
717 ctx->accepted_types = accepted_types;
718
719 ctx->handle->cb = cb;
720 ctx->handle->pw = pw;
721
722 error = llcache_handle_retrieve(url, flags, referer, post,
724 &ctx->llcache);
725 if (error != NSERROR_OK) {
726 /* error retrieving handle so free context and return error */
727 free((char *) ctx->child.charset);
728 free(ctx->handle);
729 free(ctx);
730 } else {
731 /* successfully started fetch so add new context to list */
733
734 *result = ctx->handle;
735 }
736 return error;
737}
738
739/* See hlcache.h for documentation */
741{
742 if (handle->entry != NULL) {
745 } else {
748 ictx) {
749 if (ictx->handle == handle &&
750 ictx->migrate_target == false) {
751 /* This is the nascent context for us,
752 * so abort the fetch */
753 llcache_handle_abort(ictx->llcache);
754 llcache_handle_release(ictx->llcache);
755 /* Remove us from the ring */
757 /* Throw us away */
758 free((char *) ictx->child.charset);
759 free(ictx);
760 /* And stop */
762 ictx);
763 }
765 }
766
767 handle->cb = NULL;
768 handle->pw = NULL;
769
770 free(handle);
771
772 return NSERROR_OK;
773}
774
775/* See hlcache.h for documentation */
777{
778 if ((handle != NULL) && (handle->entry != NULL)) {
779 return handle->entry->content;
780 }
781
782 return NULL;
783}
784
785/* See hlcache.h for documentation */
787{
788 struct hlcache_entry *entry = handle->entry;
789 struct content *c;
790
791 if (entry == NULL) {
792 /* This handle is not yet associated with a cache entry.
793 * The implication is that the fetch for the handle has
794 * not progressed to the point where the entry can be
795 * created. */
796
799 ictx) {
800 if (ictx->handle == handle &&
801 ictx->migrate_target == false) {
802 /* This is the nascent context for us,
803 * so abort the fetch */
804 llcache_handle_abort(ictx->llcache);
805 llcache_handle_release(ictx->llcache);
806 /* Remove us from the ring */
808 /* Throw us away */
809 free((char *) ictx->child.charset);
810 free(ictx);
811 /* And stop */
813 ictx);
814 }
816
817 return NSERROR_OK;
818 }
819
820 c = entry->content;
821
822 if (content_count_users(c) > 1) {
823 /* We are not the only user of 'c' so clone it. */
824 struct content *clone = content_clone(c);
825
826 if (clone == NULL)
827 return NSERROR_NOMEM;
828
829 entry = calloc(sizeof(struct hlcache_entry), 1);
830
831 if (entry == NULL) {
832 content_destroy(clone);
833 return NSERROR_NOMEM;
834 }
835
836 if (content_add_user(clone,
837 hlcache_content_callback, handle) == false) {
838 content_destroy(clone);
839 free(entry);
840 return NSERROR_NOMEM;
841 }
842
844
845 entry->content = clone;
846 handle->entry = entry;
847 entry->prev = NULL;
848 entry->next = hlcache->content_list;
849 if (hlcache->content_list != NULL)
850 hlcache->content_list->prev = entry;
851 hlcache->content_list = entry;
852
853 c = clone;
854 }
855
856 return content_abort(c);
857}
858
859/* See hlcache.h for documentation */
861 hlcache_handle_callback cb, void *pw)
862{
863 handle->cb = cb;
864 handle->pw = pw;
865
866 return NSERROR_OK;
867}
868
870{
871 *result = NULL;
873}
874
875/* See hlcache.h for documentation */
877{
878 nsurl *result = NULL;
879
880 assert(handle != NULL);
881
882 if (handle->entry != NULL) {
884 } else {
887 ictx) {
888 if (ictx->handle == handle) {
889 /* This is the nascent context for us */
890 result = llcache_handle_get_url(ictx->llcache);
891
892 /* And stop */
894 ictx);
895 }
897 }
898
899 return result;
900}
STATIC char result[100]
Definition: arexx.c:77
void content_destroy(struct content *c)
Destroy and free a content.
Definition: content.c:354
void content_remove_user(struct content *c, void(*callback)(struct content *c, content_msg msg, const union content_msg_data *data, void *pw), void *pw)
Remove a callback user.
Definition: content.c:684
uint32_t content_count_users(struct content *c)
Count users for the content.
Definition: content.c:718
bool content_is_shareable(struct content *c)
Determine if a content is shareable.
Definition: content.c:745
void content_set_error(struct content *c)
Put a content in status CONTENT_STATUS_ERROR and unlock the content.
Definition: content.c:313
content_status content__get_status(struct content *c)
Retrieve status of content.
Definition: content.c:1131
nsurl * content_get_url(struct content *c)
Retrieve URL associated with content.
Definition: content.c:1051
bool content_add_user(struct content *c, void(*callback)(struct content *c, content_msg msg, const union content_msg_data *data, void *pw), void *pw)
Register a user for callbacks.
Definition: content.c:654
struct content * content_clone(struct content *c)
Clone a content object in its current state.
Definition: content.c:1368
bool content_matches_quirks(struct content *c, bool quirks)
Determine if quirks mode matches.
Definition: content.c:735
nserror content_abort(struct content *c)
Abort a content object.
Definition: content.c:1448
const llcache_handle * content_get_llcache_handle(struct content *c)
Retrieve the low-level cache handle for a content.
Definition: content.c:1358
content_status content_get_status(hlcache_handle *h)
Retrieve status of content.
Definition: content.c:1124
content_type content_factory_type_from_mime_type(lwc_string *mime_type)
Compute the generic content type for a MIME type.
struct content * content_factory_create_content(llcache_handle *llcache, const char *fallback_charset, bool quirks, lwc_string *effective_type)
Create a content object.
Protected interface to Content handling.
content_status
Status of a content.
Definition: content_type.h:87
@ CONTENT_STATUS_READY
Some parts of content still being loaded, but can be displayed.
Definition: content_type.h:92
@ CONTENT_STATUS_DONE
Content has completed all processing.
Definition: content_type.h:95
@ CONTENT_STATUS_ERROR
Error occurred, content will be destroyed imminently.
Definition: content_type.h:98
@ CONTENT_STATUS_LOADING
Content is being fetched or converted and is not safe to display.
Definition: content_type.h:89
content_type
The type of a content.
Definition: content_type.h:53
@ CONTENT_IMAGE
All images.
Definition: content_type.h:67
@ CONTENT_NONE
no type for content
Definition: content_type.h:55
content_msg
Used in callbacks to indicate what has occurred.
Definition: content_type.h:105
@ CONTENT_MSG_DONE
content has finished processing
Definition: content_type.h:119
@ CONTENT_MSG_DOWNLOAD
download, not for display
Definition: content_type.h:140
@ CONTENT_MSG_LOADING
fetching or converting
Definition: content_type.h:113
@ CONTENT_MSG_ERROR
error occurred
Definition: content_type.h:122
@ CONTENT_MSG_REDIRECT
fetch url redirect occured
Definition: content_type.h:125
@ CONTENT_MSG_SSL_CERTS
Content is from SSL and this is its chain.
Definition: content_type.h:110
@ CONTENT_MSG_READY
may be displayed
Definition: content_type.h:116
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOT_FOUND
Requested item not found.
Definition: errors.h:34
@ NSERROR_NEED_DATA
More data needed.
Definition: errors.h:46
@ NSERROR_UNKNOWN
Unknown error - DO NOT USE.
Definition: errors.h:31
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_CLONE_FAILED
Failed to clone handle.
Definition: errors.h:37
@ NSERROR_OK
No error.
Definition: errors.h:30
const char * type
Definition: filetype.cpp:44
struct netsurf_table * guit
The global interface table.
Definition: gui_factory.c:49
Interface to core interface table.
static bool hlcache_type_is_acceptable(lwc_string *mime_type, content_type accepted_types, content_type *computed_type)
Determine if the specified MIME type is acceptable.
Definition: hlcache.c:171
nserror hlcache_initialise(const struct hlcache_parameters *hlcache_parameters)
Initialise the high-level cache, preparing the llcache also.
Definition: hlcache.c:552
static nserror hlcache_migrate_ctx(hlcache_retrieval_ctx *ctx, lwc_string *effective_type)
Migrate a retrieval context into its final destination content.
Definition: hlcache.c:348
static void hlcache_clean(void *force_clean_flag)
Attempt to clean the cache.
Definition: hlcache.c:111
struct content * hlcache_handle_get_content(const hlcache_handle *handle)
Retrieve a content object from a cache handle.
Definition: hlcache.c:776
static void hlcache_content_callback(struct content *c, content_msg msg, const union content_msg_data *data, void *pw)
Veneer between content callback API and hlcache callback API.
Definition: hlcache.c:191
nsurl * hlcache_handle_get_url(const hlcache_handle *handle)
Definition: hlcache.c:876
void hlcache_finalise(void)
Finalise the high-level cache, destroying any remaining contents.
Definition: hlcache.c:584
void hlcache_stop(void)
Stop the high-level cache periodic functionality so that the exit sequence can run.
Definition: hlcache.c:577
static nserror hlcache_find_content(hlcache_retrieval_ctx *ctx, lwc_string *effective_type)
Find a content for the high-level cache handle.
Definition: hlcache.c:225
static nserror hlcache_llcache_callback(llcache_handle *handle, const llcache_event *event, void *pw)
Handler for low-level cache events.
Definition: hlcache.c:429
nserror hlcache_handle_abort(hlcache_handle *handle)
Abort a high-level cache fetch.
Definition: hlcache.c:786
static struct hlcache_s * hlcache
high level cache state
Definition: hlcache.c:100
nserror hlcache_handle_clone(hlcache_handle *handle, hlcache_handle **result)
Clone a high level cache handle.
Definition: hlcache.c:869
nserror hlcache_handle_replace_callback(hlcache_handle *handle, hlcache_handle_callback cb, void *pw)
Replace a high-level cache handle's callback.
Definition: hlcache.c:860
nserror hlcache_handle_release(hlcache_handle *handle)
Release a high-level cache handle.
Definition: hlcache.c:740
nserror hlcache_handle_retrieve(nsurl *url, uint32_t flags, nsurl *referer, llcache_post_data *post, hlcache_handle_callback cb, void *pw, hlcache_child_context *child, content_type accepted_types, hlcache_handle **result)
Retrieve a high-level cache handle for an object.
Definition: hlcache.c:679
High-level resource cache interface.
nserror(* hlcache_handle_callback)(hlcache_handle *handle, const hlcache_event *event, void *pw)
Client callback for high-level cache events.
Definition: hlcache.h:63
@ HLCACHE_RETRIEVE_SNIFF_TYPE
Definition: hlcache.h:75
@ HLCACHE_RETRIEVE_MAY_DOWNLOAD
It's permitted to convert this request into a download.
Definition: hlcache.h:73
HTTP header parsing functions.
Public content interface.
Interface to platform-specific miscellaneous browser operation table.
Netsurf additional integer type formatting macros.
nserror llcache_initialise(const struct llcache_parameters *prm)
Initialise the low-level cache.
Definition: llcache.c:3891
void llcache_clean(bool purge)
Cause the low-level cache to attempt to perform cleanup.
Definition: llcache.c:3725
nserror llcache_handle_abort(llcache_handle *handle)
Abort a low-level fetch, informing all users of this action.
Definition: llcache.c:4098
void llcache_finalise(void)
Finalise the low-level cache.
Definition: llcache.c:3916
bool llcache_handle_references_same_object(const llcache_handle *a, const llcache_handle *b)
Determine if the same underlying object is referenced by the given handles.
Definition: llcache.c:4229
nsurl * llcache_handle_get_url(const llcache_handle *handle)
Retrieve the post-redirect URL of a low-level cache object.
Definition: llcache.c:4195
const char * llcache_handle_get_header(const llcache_handle *handle, const char *key)
Retrieve a header value associated with a low-level cache object.
Definition: llcache.c:4210
nserror llcache_handle_retrieve(nsurl *url, uint32_t flags, nsurl *referer, const llcache_post_data *post, llcache_handle_callback cb, void *pw, llcache_handle **result)
Retrieve a handle for a low-level cache object.
Definition: llcache.c:3990
nserror llcache_handle_force_stream(llcache_handle *handle)
Force a low-level cache handle into streaming mode.
Definition: llcache.c:4160
nserror llcache_handle_release(llcache_handle *handle)
Release a low-level cache handle.
Definition: llcache.c:4058
@ LLCACHE_EVENT_DONE
Finished fetching data.
Definition: llcache.h:71
@ LLCACHE_EVENT_ERROR
An error occurred during fetch.
Definition: llcache.h:73
@ LLCACHE_EVENT_GOT_CERTS
SSL certificates arrived.
Definition: llcache.h:68
@ LLCACHE_EVENT_REDIRECT
Fetch URL redirect occured.
Definition: llcache.h:76
@ LLCACHE_EVENT_PROGRESS
Fetch progress update.
Definition: llcache.h:74
@ LLCACHE_EVENT_HAD_HEADERS
Received all headers.
Definition: llcache.h:69
@ LLCACHE_EVENT_HAD_DATA
Received some data.
Definition: llcache.h:70
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
nserror mimesniff_compute_effective_type(const char *content_type_header, const uint8_t *data, size_t len, bool sniff_allowed, bool image_only, lwc_string **effective_type)
Compute the effective MIME type for an object.
Definition: mimesniff.c:563
MIME type sniffer interface.
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
Ring list structure.
#define RING_ITERATE_STOP(ring, iteratorptr)
Definition: ring.h:133
#define RING_REMOVE(ring, element)
Remove the given element from the specified ring.
Definition: ring.h:53
#define RING_INSERT(ring, element)
Insert the given item into the specified ring.
Definition: ring.h:40
#define RING_ITERATE_END(ring, iteratorptr)
Definition: ring.h:136
#define RING_ITERATE_START(ringtype, ring, iteratorptr)
Definition: ring.h:127
Interface to utility string handling.
Content which corresponds to a single URL.
nserror(* schedule)(int t, void(*callback)(void *p), void *p)
Schedule a callback.
Definition: misc.h:58
Context for retrieving a child object.
Definition: hlcache.h:37
bool quirks
Whether parent is quirky.
Definition: hlcache.h:39
const char * charset
Charset of parent.
Definition: hlcache.h:38
Entry in high-level cache.
Definition: hlcache.c:74
hlcache_entry * next
Next sibling.
Definition: hlcache.c:77
hlcache_entry * prev
Previous sibling.
Definition: hlcache.c:78
struct content * content
Pointer to associated content.
Definition: hlcache.c:75
High-level cache event.
Definition: hlcache.h:43
content_msg type
Event type.
Definition: hlcache.h:44
union content_msg_data data
Event data.
Definition: hlcache.h:45
High-level cache handle.
Definition: hlcache.c:66
hlcache_handle_callback cb
Client callback.
Definition: hlcache.c:69
void * pw
Client data.
Definition: hlcache.c:70
hlcache_entry * entry
Pointer to cache entry.
Definition: hlcache.c:67
unsigned int bg_clean_time
How frequently the background cache clean process is run (ms)
Definition: hlcache.h:50
struct llcache_parameters llcache
Definition: hlcache.h:52
High-level cache retrieval context.
Definition: hlcache.c:48
hlcache_child_context child
Child context.
Definition: hlcache.c:60
llcache_handle * llcache
Low-level cache handle.
Definition: hlcache.c:52
struct hlcache_retrieval_ctx * r_next
Next retrieval context in the ring.
Definition: hlcache.c:50
bool migrate_target
Whether this context is the migration target.
Definition: hlcache.c:62
struct hlcache_retrieval_ctx * r_prev
Previous retrieval context in the ring.
Definition: hlcache.c:49
content_type accepted_types
Accepted types.
Definition: hlcache.c:58
uint32_t flags
Retrieval flags.
Definition: hlcache.c:56
hlcache_handle * handle
High-level handle for object.
Definition: hlcache.c:54
Current state of the cache.
Definition: hlcache.c:85
hlcache_retrieval_ctx * retrieval_ctx_ring
Ring of retrieval contexts.
Definition: hlcache.c:92
struct hlcache_parameters params
Definition: hlcache.c:86
hlcache_entry * content_list
List of cached content objects.
Definition: hlcache.c:89
unsigned int hit_count
Definition: hlcache.c:95
unsigned int miss_count
Definition: hlcache.c:96
Low-level cache events.
Definition: llcache.h:85
struct llcache_event::@124::@125 data
Received data.
size_t len
Byte length of buffer.
Definition: llcache.h:90
llcache_event_type type
Type of event.
Definition: llcache.h:86
const uint8_t * buf
Buffer of data.
Definition: llcache.h:89
Handle to low-level cache object.
Definition: llcache.c:76
POST data object for low-level cache requests.
Definition: llcache.h:40
struct gui_misc_table * misc
Browser table.
Definition: gui_table.h:57
Extra data for some content_msg messages.
Definition: content.h:60
struct content_msg_data::@99 errordata
CONTENT_MSG_ERROR - Error from content or underlying fetch.
nserror errorcode
The error code to convey meaning.
Definition: content.h:88
const char * errormsg
The message.
Definition: content.h:95
const struct cert_chain * chain
CONTENT_MSG_SSL_CERTS - The certificate chain from the underlying fetch.
Definition: content.h:79
struct nsurl * to
Redirect target.
Definition: content.h:103
struct nsurl * from
Redirect origin.
Definition: content.h:102
struct llcache_handle * download
CONTENT_MSG_DOWNLOAD - Low-level cache handle.
Definition: content.h:133
struct content_msg_data::@100 redirect
CONTENT_MSG_REDIRECT - Redirect info.
Interface to a number of general purpose functionality.