00c7c811ff4368c379f7ed69c6d26a5c82660522
[WebKit-https.git] / WebCore / khtml / misc / loader.h
1 /*
2     This file is part of the KDE libraries
3
4     Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
5     Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
6     Copyright (C) 2003 Apple Computer, Inc.
7
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Library General Public
10     License as published by the Free Software Foundation; either
11     version 2 of the License, or (at your option) any later version.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Library General Public License for more details.
17
18     You should have received a copy of the GNU Library General Public License
19     along with this library; see the file COPYING.LIB.  If not, write to
20     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21     Boston, MA 02111-1307, USA.
22
23     This class provides all functionality needed for loading images, style sheets and html
24     pages from the web. It has a memory cache for these objects.
25 */
26 #ifndef _khtml_loader_h
27 #define _khtml_loader_h
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33 #include <time.h>
34
35 #include "loader_client.h"
36 #ifdef HAVE_LIBJPEG
37 #include "loader_jpeg.h"
38 #endif
39
40 #include <stdlib.h>
41 #include <qptrlist.h>
42 #include <qobject.h>
43 #include <qptrdict.h>
44 #include <qdict.h>
45 #include <qpixmap.h>
46 #include <qbuffer.h>
47 #include <qstringlist.h>
48 #include <qtextcodec.h>
49
50 #include <kurl.h>
51 #include <kio/global.h>
52
53 #include <khtml_settings.h>
54 #include <dom/dom_string.h>
55
56 class QMovie;
57 class KHTMLPart;
58
59 namespace KIO {
60   class Job;
61   class TransferJob;
62 }
63
64 namespace DOM
65 {
66     class CSSStyleSheetImpl;
67     class DocumentImpl;
68 };
69
70 #if APPLE_CHANGES
71 class KWQLoader;
72 #endif
73
74 namespace khtml
75 {
76     class CachedObject;
77     class Request;
78     class DocLoader;
79
80  #define MAX_LRU_LISTS 20
81     
82     struct LRUList {
83         CachedObject* m_head;
84         CachedObject* m_tail;
85     
86         LRUList();
87         ~LRUList();
88     };
89     
90     /**
91      * @internal
92      *
93      * A cached object. Classes who want to use this object should derive
94      * from CachedObjectClient, to get the function calls in case the requested data has arrived.
95      *
96      * This class also does the actual communication with kio and loads the file.
97      */
98     class CachedObject
99     {
100     public:
101         enum Type {
102             Image,
103             CSSStyleSheet,
104             Script
105 #ifdef KHTML_XSLT
106             , XSLStyleSheet
107 #endif
108 #ifndef KHTML_NO_XBL
109             , XBL
110 #endif
111         };
112
113         enum Status {
114             NotCached,    // this URL is not cached
115             Unknown,      // let imagecache decide what to do with it
116             New,          // inserting new image
117         Pending,      // only partially loaded
118             Persistent,   // never delete this pixmap
119             Cached,       // regular case
120             Uncacheable   // too big to be cached,
121         };                // will be destroyed as soon as possible
122
123         CachedObject(const DOM::DOMString &url, Type type, KIO::CacheControl _cachePolicy, time_t _expireDate, int size = 0)
124         {
125             m_url = url;
126             m_type = type;
127             m_status = Pending;
128             m_size = size;
129             m_free = false;
130             m_cachePolicy = _cachePolicy;
131             m_request = 0;
132 #if APPLE_CHANGES
133         m_response = 0;
134 #endif            
135             m_expireDate = _expireDate;
136         m_deleted = false;
137         m_expireDateChanged = false;
138         
139         m_accessCount = 0;
140         
141         m_nextInLRUList = 0;
142         m_prevInLRUList = 0;
143         }
144         virtual ~CachedObject();
145
146         virtual void data( QBuffer &buffer, bool eof) = 0;
147         virtual void error( int err, const char *text ) = 0;
148
149         const DOM::DOMString &url() const { return m_url; }
150         Type type() const { return m_type; }
151
152         virtual void ref(CachedObjectClient *consumer);
153         virtual void deref(CachedObjectClient *consumer);
154
155         int count() const { return m_clients.count(); }
156
157         Status status() const { return m_status; }
158
159         int size() const { return m_size; }
160
161     int accessCount() const { return m_accessCount; }
162     void increaseAccessCount() { m_accessCount++; }
163     
164         /**
165          * computes the status of an object after loading.
166          * the result depends on the objects size and the size of the cache
167          * also updates the expire date on the cache entry file
168          */
169         void finish();
170
171         /**
172          * Called by the cache if the object has been removed from the cache dict
173          * while still being referenced. This means the object should kill itself
174          * if its reference counter drops down to zero.
175          */
176         void setFree( bool b ) { m_free = b; }
177
178         KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
179
180         void setRequest(Request *_request);
181
182 #if APPLE_CHANGES
183         void *response() { return m_response; }
184         void setResponse (void *response);
185 #endif
186         bool canDelete() const { return (m_clients.count() == 0 && !m_request); }
187
188         void setExpireDate(time_t _expireDate, bool changeHttpCache);
189         
190         bool isExpired() const;
191
192         virtual bool schedule() const { return false; }
193
194         /**
195          * List of acceptable mimetypes seperated by ",". A mimetype may contain a wildcard.
196          */
197         // e.g. "text/*"
198         QString accept() const { return m_accept; }
199         void setAccept(const QString &_accept) { m_accept = _accept; }
200
201     protected:
202         void setSize(int size);
203         
204         QPtrDict<CachedObjectClient> m_clients;
205
206         DOM::DOMString m_url;
207         QString m_accept;
208         Request *m_request;
209 #if APPLE_CHANGES
210         void *m_response;
211 #endif
212         Type m_type;
213         Status m_status;
214     private:
215         int m_size;
216     int m_accessCount;
217     
218     protected:
219         time_t m_expireDate;
220         KIO::CacheControl m_cachePolicy;
221         bool m_free : 1;
222         bool m_deleted : 1;
223         bool m_loading : 1;
224         bool m_expireDateChanged : 1;
225     
226     private:
227         bool allowInLRUList() { return canDelete() && status() != Persistent; }
228         
229         CachedObject *m_nextInLRUList;
230         CachedObject *m_prevInLRUList;
231         friend class Cache;
232     };
233
234
235     /**
236      * a cached style sheet
237      */
238     class CachedCSSStyleSheet : public CachedObject
239     {
240     public:
241         CachedCSSStyleSheet(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate, const QString& charset);
242         CachedCSSStyleSheet(const DOM::DOMString &url, const QString &stylesheet_data);
243         virtual ~CachedCSSStyleSheet();
244
245         const DOM::DOMString &sheet() const { return m_sheet; }
246
247         virtual void ref(CachedObjectClient *consumer);
248         virtual void deref(CachedObjectClient *consumer);
249
250         virtual void data( QBuffer &buffer, bool eof );
251         virtual void error( int err, const char *text );
252
253         virtual bool schedule() const { return true; }
254
255         void checkNotify();
256
257     protected:
258         DOM::DOMString m_sheet;
259         QTextCodec* m_codec;
260     };
261
262     /**
263      * a cached script
264      */
265     class CachedScript : public CachedObject
266     {
267     public:
268         CachedScript(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate, const QString& charset);
269         CachedScript(const DOM::DOMString &url, const QString &script_data);
270         virtual ~CachedScript();
271
272         const DOM::DOMString &script() const { return m_script; }
273
274         virtual void ref(CachedObjectClient *consumer);
275         virtual void deref(CachedObjectClient *consumer);
276
277         virtual void data( QBuffer &buffer, bool eof );
278         virtual void error( int err, const char *text );
279
280         virtual bool schedule() const { return false; }
281
282         void checkNotify();
283
284         bool isLoaded() const { return !m_loading; }
285
286     protected:
287         DOM::DOMString m_script;
288         QTextCodec* m_codec;
289     };
290
291     class ImageSource;
292
293     /**
294      * a cached image
295      */
296     class CachedImage : public QObject, public CachedObject
297     {
298         Q_OBJECT
299     public:
300         CachedImage(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate);
301         virtual ~CachedImage();
302
303         const QPixmap &pixmap() const;
304         const QPixmap &tiled_pixmap(const QColor& bg);
305
306         QSize pixmap_size() const;    // returns the size of the complete (i.e. when finished) loading
307         QRect valid_rect() const;     // returns the rectangle of pixmap that has been loaded already
308
309         void ref(CachedObjectClient *consumer);
310         virtual void deref(CachedObjectClient *consumer);
311
312         virtual void data( QBuffer &buffer, bool eof );
313         virtual void error( int err, const char *text );
314
315         bool isTransparent() const { return isFullyTransparent; }
316         bool isErrorImage() const { return errorOccured; }
317
318         void setShowAnimations( KHTMLSettings::KAnimationAdvice );
319
320         virtual bool schedule() const { return true; }
321
322         void checkNotify();
323
324     protected:
325         void clear();
326
327     private slots:
328         /**
329          * gets called, whenever a QMovie changes frame
330          */
331         void movieUpdated( const QRect &rect );
332         void movieStatus(int);
333         void movieResize(const QSize&);
334         void deleteMovie();
335
336     private:
337         void do_notify(const QPixmap& p, const QRect& r);
338
339         QMovie* m;
340         QPixmap* p;
341         QPixmap* bg;
342         QRgb bgColor;
343         mutable QPixmap* pixPart;
344
345         ImageSource* imgSource;
346         const char* formatType;  // Is the name of the movie format type
347
348         int width;
349         int height;
350
351         // Is set if movie format type ( incremental/animation) was checked
352         bool typeChecked : 1;
353         bool isFullyTransparent : 1;
354         bool errorOccured : 1;
355         bool monochrome : 1;
356         KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
357
358         friend class Cache;
359
360 #if APPLE_CHANGES
361     public:
362         int dataSize() const { return m_dataSize; }
363     private:
364         int m_dataSize;
365 #endif
366     };
367
368 #ifdef KHTML_XSLT
369     class CachedXSLStyleSheet : public CachedObject
370     {
371 public:
372         CachedXSLStyleSheet(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate);
373
374         const DOM::DOMString& sheet() const { return m_sheet; }
375         
376         virtual void ref(CachedObjectClient *consumer);
377         virtual void deref(CachedObjectClient *consumer);
378         
379         virtual void data(QBuffer &buffer, bool eof);
380         virtual void error(int err, const char *text);
381         
382         virtual bool schedule() const { return true; }
383         
384         void checkNotify();
385         
386 protected:
387         DOM::DOMString m_sheet;
388         QTextCodec* m_codec;
389     };
390 #endif
391     
392 #ifndef KHTML_NO_XBL
393     class CachedXBLDocument : public CachedObject
394     {
395     public:
396         CachedXBLDocument(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate);
397         virtual ~CachedXBLDocument();
398         
399         XBL::XBLDocumentImpl* document() const { return m_document; }
400         
401         virtual void ref(CachedObjectClient *consumer);
402         virtual void deref(CachedObjectClient *consumer);
403         
404         virtual void data( QBuffer &buffer, bool eof );
405         virtual void error( int err, const char *text );
406         
407         virtual bool schedule() const { return true; }
408         
409         void checkNotify();
410         
411 protected:
412         XBL::XBLDocumentImpl* m_document;
413         QTextCodec* m_codec;
414     };
415 #endif
416
417     /**
418      * @internal
419      *
420      * Manages the loading of scripts/images/stylesheets for a particular document
421      */
422     class DocLoader
423     {
424     public:
425         DocLoader(KHTMLPart*, DOM::DocumentImpl*);
426         ~DocLoader();
427
428         CachedImage *requestImage( const DOM::DOMString &url);
429         CachedCSSStyleSheet *requestStyleSheet( const DOM::DOMString &url, const QString& charset);
430         CachedScript *requestScript( const DOM::DOMString &url, const QString& charset);
431
432 #ifdef KHTML_XSLT
433         CachedXSLStyleSheet* requestXSLStyleSheet(const DOM::DOMString& url);
434 #endif
435 #ifndef KHTML_NO_XBL
436         CachedXBLDocument* requestXBLDocument(const DOM::DOMString &url);
437 #endif
438
439         bool autoloadImages() const { return m_bautoloadImages; }
440         KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
441         KHTMLSettings::KAnimationAdvice showAnimations() const { return m_showAnimations; }
442         time_t expireDate() const { return m_expireDate; }
443         KHTMLPart* part() const { return m_part; }
444         DOM::DocumentImpl* doc() const { return m_doc; }
445
446         void setExpireDate( time_t );
447         void setAutoloadImages( bool );
448         void setCachePolicy( KIO::CacheControl cachePolicy );
449         void setShowAnimations( KHTMLSettings::KAnimationAdvice );
450         void removeCachedObject( CachedObject*) const;
451
452     private:
453         bool needReload(const KURL &fullUrl);
454
455         friend class Cache;
456         friend class DOM::DocumentImpl;
457
458         QStringList m_reloadedURLs;
459         mutable QPtrList<CachedObject> m_docObjects;
460         time_t m_expireDate;
461         KIO::CacheControl m_cachePolicy;
462         bool m_bautoloadImages : 1;
463         KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
464         KHTMLPart* m_part;
465         DOM::DocumentImpl* m_doc;
466     };
467
468     /**
469      * @internal
470      */
471     class Request
472     {
473     public:
474         Request(DocLoader* dl, CachedObject *_object, bool _incremental);
475         ~Request();
476         bool incremental;
477         QBuffer m_buffer;
478         CachedObject *object;
479         DocLoader* m_docLoader;
480      };
481
482     /**
483      * @internal
484      */
485     class Loader : public QObject
486     {
487         Q_OBJECT
488
489     public:
490         Loader();
491         ~Loader();
492
493         void load(DocLoader* dl, CachedObject *object, bool incremental = true);
494
495         int numRequests( DocLoader* dl ) const;
496         void cancelRequests( DocLoader* dl );
497
498         // may return 0L
499         KIO::Job *jobForRequest( const DOM::DOMString &url ) const;
500
501 #if APPLE_CHANGES
502         KWQLoader *kwq;
503 #endif
504
505     signals:
506         void requestStarted( khtml::DocLoader* dl, khtml::CachedObject* obj );
507         void requestDone( khtml::DocLoader* dl, khtml::CachedObject *obj );
508         void requestFailed( khtml::DocLoader* dl, khtml::CachedObject *obj );
509
510     protected slots:
511         void slotFinished( KIO::Job * );
512 #if APPLE_CHANGES
513         void slotData( KIO::Job *, const char *data, int size );
514         void slotReceivedResponse ( KIO::Job *, void *response );
515 #else
516         void slotData( KIO::Job *, const QByteArray & );
517 #endif
518
519     private:
520         void servePendingRequests();
521
522         QPtrList<Request> m_requestsPending;
523         QPtrDict<Request> m_requestsLoading;
524 #ifdef HAVE_LIBJPEG
525         KJPEGFormatType m_jpegloader;
526 #endif
527     };
528
529         /**
530      * @internal
531      *
532      * Provides a cache/loader for objects needed for displaying the html page.
533      * At the moment these are stylesheets, scripts and images
534      */
535     class Cache
536     {
537         friend class DocLoader;
538     public:
539         /**
540          * init the cache in case it's not already. This needs to get called once
541          * before using it.
542          */
543         static void init();
544
545         /**
546          * Ask the cache for some url. Will return a cachedObject, and
547          * load the requested data in case it's not cahced
548          * if the DocLoader is zero, the url must be full-qualified.
549          * Otherwise, it is automatically base-url expanded
550          */
551         static CachedImage *requestImage( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0);
552         static CachedImage *requestImage( DocLoader* l, const KURL &url, bool reload=false, time_t _expireDate=0);
553
554         /**
555          * Ask the cache for some url. Will return a cachedObject, and
556          * load the requested data in case it's not cached
557          */
558         static CachedCSSStyleSheet *requestStyleSheet( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0, const QString& charset = QString::null);
559
560 #ifdef KHTML_XSLT
561         // Ask the cache for an XSL stylesheet.
562         static CachedXSLStyleSheet* requestXSLStyleSheet(DocLoader* l, const DOM::DOMString &url, 
563                                                          bool reload=false, time_t _expireDate=0);
564 #endif
565 #ifndef KHTML_NO_XBL
566         // Ask the cache for an XBL document.
567         static CachedXBLDocument* requestXBLDocument(DocLoader* l, const DOM::DOMString &url, 
568                                                      bool reload=false, time_t _expireDate=0);
569 #endif
570
571         /**
572          * Pre-loads a stylesheet into the cache.
573          */
574         static void preloadStyleSheet(const QString &url, const QString &stylesheet_data);
575
576         /**
577          * Ask the cache for some url. Will return a cachedObject, and
578          * load the requested data in case it's not cahced
579          */
580         static CachedScript *requestScript( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0, const QString& charset=QString::null);
581
582         /**
583          * Pre-loads a script into the cache.
584          */
585         static void preloadScript(const QString &url, const QString &script_data);
586
587         /**
588          * sets the size of the cache. This will only hod approximately, since the size some
589          * cached objects (like stylesheets) take up in memory is not exaclty known.
590          */
591         static void setSize( int bytes );
592         /**
593          * returns the size of the cache
594          */
595         static int size() { return maxSize; };
596
597         static int maxCacheableObjectSize() { return maxCacheable; }
598
599         /**
600          * prints some statistics to stdout
601          */
602         static void statistics();
603
604         /**
605          * clean up cache
606          */
607         static void flush(bool force=false);
608
609         /**
610          * clears the cache
611          * Warning: call this only at the end of your program, to clean
612          * up memory (useful for finding memory holes)
613          */
614         static void clear();
615
616         static Loader *loader() { return m_loader; }
617
618         static QPixmap *nullPixmap;
619         static QPixmap *brokenPixmap;
620
621         static void removeCacheEntry( CachedObject *object );
622
623 #if APPLE_CHANGES
624         struct TypeStatistic {
625             int count;
626             int size;
627             TypeStatistic() : count(0), size(0) { }
628         };
629         
630         struct Statistics {
631             TypeStatistic images;
632             TypeStatistic movies;
633             TypeStatistic styleSheets;
634             TypeStatistic scripts;
635 #ifdef KHTML_XSLT
636             TypeStatistic xslStyleSheets;
637 #endif
638 #ifndef KHTML_NO_XBL
639             TypeStatistic xblDocs;
640 #endif
641             TypeStatistic other;
642         };
643
644         static Statistics getStatistics();
645         static void flushAll();
646         static void setCacheDisabled(bool);
647 #endif
648
649         static void insertInLRUList(CachedObject *);
650         static void removeFromLRUList(CachedObject *);
651         static bool adjustSize(CachedObject *, int sizeDelta);
652         
653         static LRUList* getLRUListFor(CachedObject* o);
654         
655         static void checkLRUAndUncacheableListIntegrity();
656
657     protected:
658         static QDict<CachedObject> *cache;
659         static QPtrList<DocLoader>* docloader;
660     
661         static int maxSize;
662         static int maxCacheable;
663         static int flushCount;
664     
665         static Loader *m_loader;
666     
667         static unsigned long s_ulRefCnt;
668     
669         static void moveToHeadOfLRUList(CachedObject *);
670     
671         static LRUList *m_LRULists;
672         static int m_totalSizeOfLRULists;
673             
674         static CachedObject *m_headOfUncacheableList;
675             
676         static int m_countOfLRUAndUncacheableLists;
677     };
678
679 };
680
681 #endif