8821cd69dfe99dfc0800f1036dc3c407340fd874
[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 #ifndef KHTML_NO_XBL
106             XBL
107 #endif
108         };
109
110         enum Status {
111             NotCached,    // this URL is not cached
112             Unknown,      // let imagecache decide what to do with it
113             New,          // inserting new image
114         Pending,      // only partially loaded
115             Persistent,   // never delete this pixmap
116             Cached,       // regular case
117             Uncacheable   // too big to be cached,
118         };                // will be destroyed as soon as possible
119
120         CachedObject(const DOM::DOMString &url, Type type, KIO::CacheControl _cachePolicy, time_t _expireDate, int size = 0)
121         {
122             m_url = url;
123             m_type = type;
124             m_status = Pending;
125             m_size = size;
126             m_free = false;
127             m_cachePolicy = _cachePolicy;
128             m_request = 0;
129 #if APPLE_CHANGES
130         m_response = 0;
131 #endif            
132             m_expireDate = _expireDate;
133         m_deleted = false;
134         m_expireDateChanged = false;
135         
136         m_accessCount = 0;
137         
138         m_nextInLRUList = 0;
139         m_prevInLRUList = 0;
140         }
141         virtual ~CachedObject();
142
143         virtual void data( QBuffer &buffer, bool eof) = 0;
144         virtual void error( int err, const char *text ) = 0;
145
146         const DOM::DOMString &url() const { return m_url; }
147         Type type() const { return m_type; }
148
149         virtual void ref(CachedObjectClient *consumer);
150         virtual void deref(CachedObjectClient *consumer);
151
152         int count() const { return m_clients.count(); }
153
154         Status status() const { return m_status; }
155
156         int size() const { return m_size; }
157
158     int accessCount() const { return m_accessCount; }
159     void increaseAccessCount() { m_accessCount++; }
160     
161         /**
162          * computes the status of an object after loading.
163          * the result depends on the objects size and the size of the cache
164          * also updates the expire date on the cache entry file
165          */
166         void finish();
167
168         /**
169          * Called by the cache if the object has been removed from the cache dict
170          * while still being referenced. This means the object should kill itself
171          * if its reference counter drops down to zero.
172          */
173         void setFree( bool b ) { m_free = b; }
174
175         KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
176
177         void setRequest(Request *_request);
178
179 #if APPLE_CHANGES
180         void *response() { return m_response; }
181         void setResponse (void *response);
182 #endif
183         bool canDelete() const { return (m_clients.count() == 0 && !m_request); }
184
185         void setExpireDate(time_t _expireDate, bool changeHttpCache);
186         
187         bool isExpired() const;
188
189         virtual bool schedule() const { return false; }
190
191         /**
192          * List of acceptable mimetypes seperated by ",". A mimetype may contain a wildcard.
193          */
194         // e.g. "text/*"
195         QString accept() const { return m_accept; }
196         void setAccept(const QString &_accept) { m_accept = _accept; }
197
198     protected:
199         void setSize(int size);
200         
201         QPtrDict<CachedObjectClient> m_clients;
202
203         DOM::DOMString m_url;
204         QString m_accept;
205         Request *m_request;
206 #if APPLE_CHANGES
207         void *m_response;
208 #endif
209         Type m_type;
210         Status m_status;
211     private:
212         int m_size;
213     int m_accessCount;
214     
215     protected:
216         time_t m_expireDate;
217         KIO::CacheControl m_cachePolicy;
218         bool m_free : 1;
219         bool m_deleted : 1;
220         bool m_loading : 1;
221         bool m_expireDateChanged : 1;
222     
223     private:
224         bool allowInLRUList() { return canDelete() && status() != Persistent; }
225         
226         CachedObject *m_nextInLRUList;
227         CachedObject *m_prevInLRUList;
228         friend class Cache;
229     };
230
231
232     /**
233      * a cached style sheet
234      */
235     class CachedCSSStyleSheet : public CachedObject
236     {
237     public:
238         CachedCSSStyleSheet(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate, const QString& charset);
239         CachedCSSStyleSheet(const DOM::DOMString &url, const QString &stylesheet_data);
240         virtual ~CachedCSSStyleSheet();
241
242         const DOM::DOMString &sheet() const { return m_sheet; }
243
244         virtual void ref(CachedObjectClient *consumer);
245         virtual void deref(CachedObjectClient *consumer);
246
247         virtual void data( QBuffer &buffer, bool eof );
248         virtual void error( int err, const char *text );
249
250         virtual bool schedule() const { return true; }
251
252         void checkNotify();
253
254     protected:
255         DOM::DOMString m_sheet;
256         QTextCodec* m_codec;
257     };
258
259     /**
260      * a cached script
261      */
262     class CachedScript : public CachedObject
263     {
264     public:
265         CachedScript(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate, const QString& charset);
266         CachedScript(const DOM::DOMString &url, const QString &script_data);
267         virtual ~CachedScript();
268
269         const DOM::DOMString &script() const { return m_script; }
270
271         virtual void ref(CachedObjectClient *consumer);
272         virtual void deref(CachedObjectClient *consumer);
273
274         virtual void data( QBuffer &buffer, bool eof );
275         virtual void error( int err, const char *text );
276
277         virtual bool schedule() const { return false; }
278
279         void checkNotify();
280
281         bool isLoaded() const { return !m_loading; }
282
283     protected:
284         DOM::DOMString m_script;
285         QTextCodec* m_codec;
286     };
287
288     class ImageSource;
289
290     /**
291      * a cached image
292      */
293     class CachedImage : public QObject, public CachedObject
294     {
295         Q_OBJECT
296     public:
297         CachedImage(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate);
298         virtual ~CachedImage();
299
300         const QPixmap &pixmap() const;
301         const QPixmap &tiled_pixmap(const QColor& bg);
302
303         QSize pixmap_size() const;    // returns the size of the complete (i.e. when finished) loading
304         QRect valid_rect() const;     // returns the rectangle of pixmap that has been loaded already
305
306         void ref(CachedObjectClient *consumer);
307         virtual void deref(CachedObjectClient *consumer);
308
309         virtual void data( QBuffer &buffer, bool eof );
310         virtual void error( int err, const char *text );
311
312         bool isTransparent() const { return isFullyTransparent; }
313         bool isErrorImage() const { return errorOccured; }
314
315         void setShowAnimations( KHTMLSettings::KAnimationAdvice );
316
317         virtual bool schedule() const { return true; }
318
319         void checkNotify();
320
321     protected:
322         void clear();
323
324     private slots:
325         /**
326          * gets called, whenever a QMovie changes frame
327          */
328         void movieUpdated( const QRect &rect );
329         void movieStatus(int);
330         void movieResize(const QSize&);
331         void deleteMovie();
332
333     private:
334         void do_notify(const QPixmap& p, const QRect& r);
335
336         QMovie* m;
337         QPixmap* p;
338         QPixmap* bg;
339         QRgb bgColor;
340         mutable QPixmap* pixPart;
341
342         ImageSource* imgSource;
343         const char* formatType;  // Is the name of the movie format type
344
345         int width;
346         int height;
347
348         // Is set if movie format type ( incremental/animation) was checked
349         bool typeChecked : 1;
350         bool isFullyTransparent : 1;
351         bool errorOccured : 1;
352         bool monochrome : 1;
353         KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
354
355         friend class Cache;
356
357 #if APPLE_CHANGES
358     public:
359         int dataSize() const { return m_dataSize; }
360     private:
361         int m_dataSize;
362 #endif
363     };
364
365 #ifndef KHTML_NO_XBL
366     class CachedXBLDocument : public CachedObject
367     {
368     public:
369         CachedXBLDocument(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate);
370         virtual ~CachedXBLDocument();
371         
372         XBL::XBLDocumentImpl* document() const { return m_document; }
373         
374         virtual void ref(CachedObjectClient *consumer);
375         virtual void deref(CachedObjectClient *consumer);
376         
377         virtual void data( QBuffer &buffer, bool eof );
378         virtual void error( int err, const char *text );
379         
380         virtual bool schedule() const { return true; }
381         
382         void checkNotify();
383         
384 protected:
385         XBL::XBLDocumentImpl* m_document;
386         QTextCodec* m_codec;
387     };
388 #endif
389
390     /**
391      * @internal
392      *
393      * Manages the loading of scripts/images/stylesheets for a particular document
394      */
395     class DocLoader
396     {
397     public:
398         DocLoader(KHTMLPart*, DOM::DocumentImpl*);
399         ~DocLoader();
400
401         CachedImage *requestImage( const DOM::DOMString &url);
402         CachedCSSStyleSheet *requestStyleSheet( const DOM::DOMString &url, const QString& charset);
403         CachedScript *requestScript( const DOM::DOMString &url, const QString& charset);
404         CachedXBLDocument* requestXBLDocument(const DOM::DOMString &url);
405         
406         bool autoloadImages() const { return m_bautoloadImages; }
407         KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
408         KHTMLSettings::KAnimationAdvice showAnimations() const { return m_showAnimations; }
409         time_t expireDate() const { return m_expireDate; }
410         KHTMLPart* part() const { return m_part; }
411         DOM::DocumentImpl* doc() const { return m_doc; }
412
413         void setExpireDate( time_t );
414         void setAutoloadImages( bool );
415         void setCachePolicy( KIO::CacheControl cachePolicy );
416         void setShowAnimations( KHTMLSettings::KAnimationAdvice );
417         void removeCachedObject( CachedObject*) const;
418
419     private:
420         bool needReload(const KURL &fullUrl);
421
422         friend class Cache;
423         friend class DOM::DocumentImpl;
424
425         QStringList m_reloadedURLs;
426         mutable QPtrList<CachedObject> m_docObjects;
427         time_t m_expireDate;
428         KIO::CacheControl m_cachePolicy;
429         bool m_bautoloadImages : 1;
430         KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
431         KHTMLPart* m_part;
432         DOM::DocumentImpl* m_doc;
433     };
434
435     /**
436      * @internal
437      */
438     class Request
439     {
440     public:
441         Request(DocLoader* dl, CachedObject *_object, bool _incremental);
442         ~Request();
443         bool incremental;
444         QBuffer m_buffer;
445         CachedObject *object;
446         DocLoader* m_docLoader;
447      };
448
449     /**
450      * @internal
451      */
452     class Loader : public QObject
453     {
454         Q_OBJECT
455
456     public:
457         Loader();
458         ~Loader();
459
460         void load(DocLoader* dl, CachedObject *object, bool incremental = true);
461
462         int numRequests( DocLoader* dl ) const;
463         void cancelRequests( DocLoader* dl );
464
465         // may return 0L
466         KIO::Job *jobForRequest( const DOM::DOMString &url ) const;
467
468 #if APPLE_CHANGES
469         KWQLoader *kwq;
470 #endif
471
472     signals:
473         void requestStarted( khtml::DocLoader* dl, khtml::CachedObject* obj );
474         void requestDone( khtml::DocLoader* dl, khtml::CachedObject *obj );
475         void requestFailed( khtml::DocLoader* dl, khtml::CachedObject *obj );
476
477     protected slots:
478         void slotFinished( KIO::Job * );
479 #if APPLE_CHANGES
480         void slotData( KIO::Job *, const char *data, int size );
481         void slotReceivedResponse ( KIO::Job *, void *response );
482 #else
483         void slotData( KIO::Job *, const QByteArray & );
484 #endif
485
486     private:
487         void servePendingRequests();
488
489         QPtrList<Request> m_requestsPending;
490         QPtrDict<Request> m_requestsLoading;
491 #ifdef HAVE_LIBJPEG
492         KJPEGFormatType m_jpegloader;
493 #endif
494     };
495
496         /**
497      * @internal
498      *
499      * Provides a cache/loader for objects needed for displaying the html page.
500      * At the moment these are stylesheets, scripts and images
501      */
502     class Cache
503     {
504         friend class DocLoader;
505     public:
506         /**
507          * init the cache in case it's not already. This needs to get called once
508          * before using it.
509          */
510         static void init();
511
512         /**
513          * Ask the cache for some url. Will return a cachedObject, and
514          * load the requested data in case it's not cahced
515          * if the DocLoader is zero, the url must be full-qualified.
516          * Otherwise, it is automatically base-url expanded
517          */
518         static CachedImage *requestImage( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0);
519
520         /**
521          * Ask the cache for some url. Will return a cachedObject, and
522          * load the requested data in case it's not cached
523          */
524         static CachedCSSStyleSheet *requestStyleSheet( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0, const QString& charset = QString::null);
525
526 #ifndef KHTML_NO_XBL
527         // Ask the cache for an XBL document.
528         static CachedXBLDocument* requestXBLDocument(DocLoader* l, const DOM::DOMString &url, 
529                                                      bool reload=false, time_t _expireDate=0);
530 #endif
531
532         /**
533          * Pre-loads a stylesheet into the cache.
534          */
535         static void preloadStyleSheet(const QString &url, const QString &stylesheet_data);
536
537         /**
538          * Ask the cache for some url. Will return a cachedObject, and
539          * load the requested data in case it's not cahced
540          */
541         static CachedScript *requestScript( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0, const QString& charset=QString::null);
542
543         /**
544          * Pre-loads a script into the cache.
545          */
546         static void preloadScript(const QString &url, const QString &script_data);
547
548         /**
549          * sets the size of the cache. This will only hod approximately, since the size some
550          * cached objects (like stylesheets) take up in memory is not exaclty known.
551          */
552         static void setSize( int bytes );
553         /**
554          * returns the size of the cache
555          */
556         static int size() { return maxSize; };
557
558         /**
559          * prints some statistics to stdout
560          */
561         static void statistics();
562
563         /**
564          * clean up cache
565          */
566         static void flush(bool force=false);
567
568         /**
569          * clears the cache
570          * Warning: call this only at the end of your program, to clean
571          * up memory (useful for finding memory holes)
572          */
573         static void clear();
574
575         static Loader *loader() { return m_loader; }
576
577         static QPixmap *nullPixmap;
578         static QPixmap *brokenPixmap;
579
580         static void removeCacheEntry( CachedObject *object );
581
582 #if APPLE_CHANGES
583         struct TypeStatistic {
584             int count;
585             int size;
586             TypeStatistic() : count(0), size(0) { }
587         };
588         
589         struct Statistics {
590             TypeStatistic images;
591             TypeStatistic movies;
592             TypeStatistic styleSheets;
593             TypeStatistic scripts;
594 #ifndef KHTML_NO_XBL
595             TypeStatistic xblDocs;
596 #endif
597             TypeStatistic other;
598         };
599
600         static Statistics getStatistics();
601         static void flushAll();
602         static void setCacheDisabled(bool);
603 #endif
604
605         static void insertInLRUList(CachedObject *);
606         static void removeFromLRUList(CachedObject *);
607         static bool adjustSize(CachedObject *, int sizeDelta);
608         
609         static LRUList* getLRUListFor(CachedObject* o);
610         
611         static void checkLRUAndUncacheableListIntegrity();
612
613     protected:
614         static QDict<CachedObject> *cache;
615         static QPtrList<DocLoader>* docloader;
616     
617         static int maxSize;
618         static int flushCount;
619     
620         static Loader *m_loader;
621     
622         static unsigned long s_ulRefCnt;
623     
624         static void moveToHeadOfLRUList(CachedObject *);
625     
626         static LRUList *m_LRULists;
627         static int m_totalSizeOfLRULists;
628             
629         static CachedObject *m_headOfUncacheableList;
630             
631         static int m_countOfLRUAndUncacheableLists;
632     };
633
634 };
635
636 #endif