#ifndef _khtml_loader_h
#define _khtml_loader_h
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <time.h>
#include "loader_client.h"
#ifdef HAVE_LIBJPEG
#include "loader_jpeg.h"
#endif
#include <stdlib.h>
#include <qptrlist.h>
#include <qobject.h>
#include <qptrdict.h>
#include <qdict.h>
#include <qpixmap.h>
#include <qbuffer.h>
#include <qstringlist.h>
#include <qtextcodec.h>
#include <kurl.h>
#include <kio/global.h>
#include <khtml_settings.h>
#include <dom/dom_string.h>
class QMovie;
class KHTMLPart;
namespace KIO {
class Job;
class TransferJob;
}
namespace DOM
{
class CSSStyleSheetImpl;
class DocumentImpl;
};
#if APPLE_CHANGES
class KWQLoader;
#endif
namespace khtml
{
class CachedObject;
class Request;
class DocLoader;
#define MAX_LRU_LISTS 20
struct LRUList {
CachedObject* m_head;
CachedObject* m_tail;
LRUList();
~LRUList();
};
class CachedObject
{
public:
enum Type {
Image,
CSSStyleSheet,
Script,
#ifndef KHTML_NO_XBL
XBL
#endif
};
enum Status {
NotCached, Unknown, New, Pending, Persistent, Cached, Uncacheable };
CachedObject(const DOM::DOMString &url, Type type, KIO::CacheControl _cachePolicy, time_t _expireDate, int size = 0)
{
m_url = url;
m_type = type;
m_status = Pending;
m_size = size;
m_free = false;
m_cachePolicy = _cachePolicy;
m_request = 0;
#if APPLE_CHANGES
m_response = 0;
#endif
m_expireDate = _expireDate;
m_deleted = false;
m_expireDateChanged = false;
m_accessCount = 0;
m_nextInLRUList = 0;
m_prevInLRUList = 0;
}
virtual ~CachedObject();
virtual void data( QBuffer &buffer, bool eof) = 0;
virtual void error( int err, const char *text ) = 0;
const DOM::DOMString &url() const { return m_url; }
Type type() const { return m_type; }
virtual void ref(CachedObjectClient *consumer);
virtual void deref(CachedObjectClient *consumer);
int count() const { return m_clients.count(); }
Status status() const { return m_status; }
int size() const { return m_size; }
int accessCount() const { return m_accessCount; }
void increaseAccessCount() { m_accessCount++; }
void finish();
void setFree( bool b ) { m_free = b; }
KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
void setRequest(Request *_request);
#if APPLE_CHANGES
void *response() { return m_response; }
void setResponse (void *response);
#endif
bool canDelete() const { return (m_clients.count() == 0 && !m_request); }
void setExpireDate(time_t _expireDate, bool changeHttpCache);
bool isExpired() const;
virtual bool schedule() const { return false; }
QString accept() const { return m_accept; }
void setAccept(const QString &_accept) { m_accept = _accept; }
protected:
void setSize(int size);
QPtrDict<CachedObjectClient> m_clients;
DOM::DOMString m_url;
QString m_accept;
Request *m_request;
#if APPLE_CHANGES
void *m_response;
#endif
Type m_type;
Status m_status;
private:
int m_size;
int m_accessCount;
protected:
time_t m_expireDate;
KIO::CacheControl m_cachePolicy;
bool m_free : 1;
bool m_deleted : 1;
bool m_loading : 1;
bool m_expireDateChanged : 1;
private:
bool allowInLRUList() { return canDelete() && status() != Persistent; }
CachedObject *m_nextInLRUList;
CachedObject *m_prevInLRUList;
friend class Cache;
};
class CachedCSSStyleSheet : public CachedObject
{
public:
CachedCSSStyleSheet(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate, const QString& charset);
CachedCSSStyleSheet(const DOM::DOMString &url, const QString &stylesheet_data);
virtual ~CachedCSSStyleSheet();
const DOM::DOMString &sheet() const { return m_sheet; }
virtual void ref(CachedObjectClient *consumer);
virtual void deref(CachedObjectClient *consumer);
virtual void data( QBuffer &buffer, bool eof );
virtual void error( int err, const char *text );
virtual bool schedule() const { return true; }
void checkNotify();
protected:
DOM::DOMString m_sheet;
QTextCodec* m_codec;
};
class CachedScript : public CachedObject
{
public:
CachedScript(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate, const QString& charset);
CachedScript(const DOM::DOMString &url, const QString &script_data);
virtual ~CachedScript();
const DOM::DOMString &script() const { return m_script; }
virtual void ref(CachedObjectClient *consumer);
virtual void deref(CachedObjectClient *consumer);
virtual void data( QBuffer &buffer, bool eof );
virtual void error( int err, const char *text );
virtual bool schedule() const { return false; }
void checkNotify();
bool isLoaded() const { return !m_loading; }
protected:
DOM::DOMString m_script;
QTextCodec* m_codec;
};
class ImageSource;
class CachedImage : public QObject, public CachedObject
{
Q_OBJECT
public:
CachedImage(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate);
virtual ~CachedImage();
const QPixmap &pixmap() const;
const QPixmap &tiled_pixmap(const QColor& bg);
QSize pixmap_size() const; QRect valid_rect() const;
void ref(CachedObjectClient *consumer);
virtual void deref(CachedObjectClient *consumer);
virtual void data( QBuffer &buffer, bool eof );
virtual void error( int err, const char *text );
bool isTransparent() const { return isFullyTransparent; }
bool isErrorImage() const { return errorOccured; }
void setShowAnimations( KHTMLSettings::KAnimationAdvice );
virtual bool schedule() const { return true; }
void checkNotify();
protected:
void clear();
private slots:
void movieUpdated( const QRect &rect );
void movieStatus(int);
void movieResize(const QSize&);
void deleteMovie();
private:
void do_notify(const QPixmap& p, const QRect& r);
QMovie* m;
QPixmap* p;
QPixmap* bg;
QRgb bgColor;
mutable QPixmap* pixPart;
ImageSource* imgSource;
const char* formatType;
int width;
int height;
bool typeChecked : 1;
bool isFullyTransparent : 1;
bool errorOccured : 1;
bool monochrome : 1;
KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
friend class Cache;
#if APPLE_CHANGES
public:
int dataSize() const { return m_dataSize; }
private:
int m_dataSize;
#endif
};
#ifndef KHTML_NO_XBL
class CachedXBLDocument : public CachedObject
{
public:
CachedXBLDocument(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, time_t _expireDate);
virtual ~CachedXBLDocument();
XBL::XBLDocumentImpl* document() const { return m_document; }
virtual void ref(CachedObjectClient *consumer);
virtual void deref(CachedObjectClient *consumer);
virtual void data( QBuffer &buffer, bool eof );
virtual void error( int err, const char *text );
virtual bool schedule() const { return true; }
void checkNotify();
protected:
XBL::XBLDocumentImpl* m_document;
QTextCodec* m_codec;
};
#endif
class DocLoader
{
public:
DocLoader(KHTMLPart*, DOM::DocumentImpl*);
~DocLoader();
CachedImage *requestImage( const DOM::DOMString &url);
CachedCSSStyleSheet *requestStyleSheet( const DOM::DOMString &url, const QString& charset);
CachedScript *requestScript( const DOM::DOMString &url, const QString& charset);
#ifndef KHTML_NO_XBL
CachedXBLDocument* requestXBLDocument(const DOM::DOMString &url);
#endif
bool autoloadImages() const { return m_bautoloadImages; }
KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
KHTMLSettings::KAnimationAdvice showAnimations() const { return m_showAnimations; }
time_t expireDate() const { return m_expireDate; }
KHTMLPart* part() const { return m_part; }
DOM::DocumentImpl* doc() const { return m_doc; }
void setExpireDate( time_t );
void setAutoloadImages( bool );
void setCachePolicy( KIO::CacheControl cachePolicy );
void setShowAnimations( KHTMLSettings::KAnimationAdvice );
void removeCachedObject( CachedObject*) const;
private:
bool needReload(const KURL &fullUrl);
friend class Cache;
friend class DOM::DocumentImpl;
QStringList m_reloadedURLs;
mutable QPtrList<CachedObject> m_docObjects;
time_t m_expireDate;
KIO::CacheControl m_cachePolicy;
bool m_bautoloadImages : 1;
KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
KHTMLPart* m_part;
DOM::DocumentImpl* m_doc;
};
class Request
{
public:
Request(DocLoader* dl, CachedObject *_object, bool _incremental);
~Request();
bool incremental;
QBuffer m_buffer;
CachedObject *object;
DocLoader* m_docLoader;
};
class Loader : public QObject
{
Q_OBJECT
public:
Loader();
~Loader();
void load(DocLoader* dl, CachedObject *object, bool incremental = true);
int numRequests( DocLoader* dl ) const;
void cancelRequests( DocLoader* dl );
KIO::Job *jobForRequest( const DOM::DOMString &url ) const;
#if APPLE_CHANGES
KWQLoader *kwq;
#endif
signals:
void requestStarted( khtml::DocLoader* dl, khtml::CachedObject* obj );
void requestDone( khtml::DocLoader* dl, khtml::CachedObject *obj );
void requestFailed( khtml::DocLoader* dl, khtml::CachedObject *obj );
protected slots:
void slotFinished( KIO::Job * );
#if APPLE_CHANGES
void slotData( KIO::Job *, const char *data, int size );
void slotReceivedResponse ( KIO::Job *, void *response );
#else
void slotData( KIO::Job *, const QByteArray & );
#endif
private:
void servePendingRequests();
QPtrList<Request> m_requestsPending;
QPtrDict<Request> m_requestsLoading;
#ifdef HAVE_LIBJPEG
KJPEGFormatType m_jpegloader;
#endif
};
class Cache
{
friend class DocLoader;
public:
static void init();
static CachedImage *requestImage( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0);
static CachedImage *requestImage( DocLoader* l, const KURL &url, bool reload=false, time_t _expireDate=0);
static CachedCSSStyleSheet *requestStyleSheet( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0, const QString& charset = QString::null);
#ifndef KHTML_NO_XBL
static CachedXBLDocument* requestXBLDocument(DocLoader* l, const DOM::DOMString &url,
bool reload=false, time_t _expireDate=0);
#endif
static void preloadStyleSheet(const QString &url, const QString &stylesheet_data);
static CachedScript *requestScript( DocLoader* l, const DOM::DOMString &url, bool reload=false, time_t _expireDate=0, const QString& charset=QString::null);
static void preloadScript(const QString &url, const QString &script_data);
static void setSize( int bytes );
static int size() { return maxSize; };
static void statistics();
static void flush(bool force=false);
static void clear();
static Loader *loader() { return m_loader; }
static QPixmap *nullPixmap;
static QPixmap *brokenPixmap;
static void removeCacheEntry( CachedObject *object );
#if APPLE_CHANGES
struct TypeStatistic {
int count;
int size;
TypeStatistic() : count(0), size(0) { }
};
struct Statistics {
TypeStatistic images;
TypeStatistic movies;
TypeStatistic styleSheets;
TypeStatistic scripts;
#ifndef KHTML_NO_XBL
TypeStatistic xblDocs;
#endif
TypeStatistic other;
};
static Statistics getStatistics();
static void flushAll();
static void setCacheDisabled(bool);
#endif
static void insertInLRUList(CachedObject *);
static void removeFromLRUList(CachedObject *);
static bool adjustSize(CachedObject *, int sizeDelta);
static LRUList* getLRUListFor(CachedObject* o);
static void checkLRUAndUncacheableListIntegrity();
protected:
static QDict<CachedObject> *cache;
static QPtrList<DocLoader>* docloader;
static int maxSize;
static int flushCount;
static Loader *m_loader;
static unsigned long s_ulRefCnt;
static void moveToHeadOfLRUList(CachedObject *);
static LRUList *m_LRULists;
static int m_totalSizeOfLRULists;
static CachedObject *m_headOfUncacheableList;
static int m_countOfLRUAndUncacheableLists;
};
};
#endif