Disable XBL. The loadBindings call was taking 0.1-0.25%. While I know how to get...
[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
405 #ifndef KHTML_NO_XBL
406         CachedXBLDocument* requestXBLDocument(const DOM::DOMString &url);
407 #endif
408
409         bool autoloadImages() const { return m_bautoloadImages; }
410         KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
411         KHTMLSettings::KAnimationAdvice showAnimations() const { return m_showAnimations; }
412         time_t expireDate() const { return m_expireDate; }
413         KHTMLPart* part() const { return m_part; }
414         DOM::DocumentImpl* doc() const { return m_doc; }
415
416         void setExpireDate( time_t );
417         void setAutoloadImages( bool );
418         void setCachePolicy( KIO::CacheControl cachePolicy );
419         void setShowAnimations( KHTMLSettings::KAnimationAdvice );
420         void removeCachedObject( CachedObject*) const;
421
422     private:
423         bool needReload(const KURL &fullUrl);
424
425         friend class Cache;
426         friend class DOM::DocumentImpl;
427
428         QStringList m_reloadedURLs;
429         mutable QPtrList<CachedObject> m_docObjects;
430         time_t m_expireDate;
431         KIO::CacheControl m_cachePolicy;
432         bool m_bautoloadImages : 1;
433         KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
434         KHTMLPart* m_part;
435         DOM::DocumentImpl* m_doc;
436     };
437
438     /**
439      * @internal
440      */
441     class Request
442     {
443     public:
444         Request(DocLoader* dl, CachedObject *_object, bool _incremental);
445         ~Request();
446         bool incremental;
447         QBuffer m_buffer;
448         CachedObject *object;
449         DocLoader* m_docLoader;
450      };
451
452     /**
453      * @internal
454      */
455     class Loader : public QObject
456     {
457         Q_OBJECT
458
459     public:
460         Loader();
461         ~Loader();
462
463         void load(DocLoader* dl, CachedObject *object, bool incremental = true);
464
465         int numRequests( DocLoader* dl ) const;
466         void cancelRequests( DocLoader* dl );
467
468         // may return 0L
469         KIO::Job *jobForRequest( const DOM::DOMString &url ) const;
470
471 #if APPLE_CHANGES
472         KWQLoader *kwq;
473 #endif
474
475     signals:
476         void requestStarted( khtml::DocLoader* dl, khtml::CachedObject* obj );
477         void requestDone( khtml::DocLoader* dl, khtml::CachedObject *obj );
478         void requestFailed( khtml::DocLoader* dl, khtml::CachedObject *obj );
479
480     protected slots:
481         void slotFinished( KIO::Job * );
482 #if APPLE_CHANGES
483         void slotData( KIO::Job *, const char *data, int size );
484         void slotReceivedResponse ( KIO::Job *, void *response );
485 #else
486         void slotData( KIO::Job *, const QByteArray & );
487 #endif
488
489     private:
490         void servePendingRequests();
491
492         QPtrList<Request> m_requestsPending;
493         QPtrDict<Request> m_requestsLoading;
494 #ifdef HAVE_LIBJPEG
495         KJPEGFormatType m_jpegloader;
496 #endif
497     };
498
499         /**
500      * @internal
501      *
502      * Provides a cache/loader for objects needed for displaying the html page.
503      * At the moment these are stylesheets, scripts and images
504      */
505     class Cache
506     {
507         friend class DocLoader;
508     public:
509         /**
510          * init the cache in case it's not already. This needs to get called once
511          * before using it.
512          */
513         static void init();
514
515         /**
516          * Ask the cache for some url. Will return a cachedObject, and
517          * load the requested data in case it's not cahced
518          * if the DocLoader is zero, the url must be full-qualified.
519          * Otherwise, it is automatically base-url expanded
520          */
521         static CachedImage *requestImage( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0);
522
523         /**
524          * Ask the cache for some url. Will return a cachedObject, and
525          * load the requested data in case it's not cached
526          */
527         static CachedCSSStyleSheet *requestStyleSheet( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0, const QString& charset = QString::null);
528
529 #ifndef KHTML_NO_XBL
530         // Ask the cache for an XBL document.
531         static CachedXBLDocument* requestXBLDocument(DocLoader* l, const DOM::DOMString &url, 
532                                                      bool reload=false, time_t _expireDate=0);
533 #endif
534
535         /**
536          * Pre-loads a stylesheet into the cache.
537          */
538         static void preloadStyleSheet(const QString &url, const QString &stylesheet_data);
539
540         /**
541          * Ask the cache for some url. Will return a cachedObject, and
542          * load the requested data in case it's not cahced
543          */
544         static CachedScript *requestScript( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0, const QString& charset=QString::null);
545
546         /**
547          * Pre-loads a script into the cache.
548          */
549         static void preloadScript(const QString &url, const QString &script_data);
550
551         /**
552          * sets the size of the cache. This will only hod approximately, since the size some
553          * cached objects (like stylesheets) take up in memory is not exaclty known.
554          */
555         static void setSize( int bytes );
556         /**
557          * returns the size of the cache
558          */
559         static int size() { return maxSize; };
560
561         /**
562          * prints some statistics to stdout
563          */
564         static void statistics();
565
566         /**
567          * clean up cache
568          */
569         static void flush(bool force=false);
570
571         /**
572          * clears the cache
573          * Warning: call this only at the end of your program, to clean
574          * up memory (useful for finding memory holes)
575          */
576         static void clear();
577
578         static Loader *loader() { return m_loader; }
579
580         static QPixmap *nullPixmap;
581         static QPixmap *brokenPixmap;
582
583         static void removeCacheEntry( CachedObject *object );
584
585 #if APPLE_CHANGES
586         struct TypeStatistic {
587             int count;
588             int size;
589             TypeStatistic() : count(0), size(0) { }
590         };
591         
592         struct Statistics {
593             TypeStatistic images;
594             TypeStatistic movies;
595             TypeStatistic styleSheets;
596             TypeStatistic scripts;
597 #ifndef KHTML_NO_XBL
598             TypeStatistic xblDocs;
599 #endif
600             TypeStatistic other;
601         };
602
603         static Statistics getStatistics();
604         static void flushAll();
605         static void setCacheDisabled(bool);
606 #endif
607
608         static void insertInLRUList(CachedObject *);
609         static void removeFromLRUList(CachedObject *);
610         static bool adjustSize(CachedObject *, int sizeDelta);
611         
612         static LRUList* getLRUListFor(CachedObject* o);
613         
614         static void checkLRUAndUncacheableListIntegrity();
615
616     protected:
617         static QDict<CachedObject> *cache;
618         static QPtrList<DocLoader>* docloader;
619     
620         static int maxSize;
621         static int flushCount;
622     
623         static Loader *m_loader;
624     
625         static unsigned long s_ulRefCnt;
626     
627         static void moveToHeadOfLRUList(CachedObject *);
628     
629         static LRUList *m_LRULists;
630         static int m_totalSizeOfLRULists;
631             
632         static CachedObject *m_headOfUncacheableList;
633             
634         static int m_countOfLRUAndUncacheableLists;
635     };
636
637 };
638
639 #endif