File indexing completed on 2023-09-24 04:06:35
0001 /* 0002 This file is part of the KDE libraries 0003 0004 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) 0005 Copyright (C) 2001-2003 Dirk Mueller <mueller@kde.org> 0006 Copyright (C) 2003 Apple Computer, Inc 0007 0008 This library is free software; you can redistribute it and/or 0009 modify it under the terms of the GNU Library General Public 0010 License as published by the Free Software Foundation; either 0011 version 2 of the License, or (at your option) any later version. 0012 0013 This library is distributed in the hope that it will be useful, 0014 but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 Library General Public License for more details. 0017 0018 You should have received a copy of the GNU Library General Public License 0019 along with this library; see the file COPYING.LIB. If not, write to 0020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 Boston, MA 02110-1301, USA. 0022 0023 This class provides all functionality needed for loading images, style sheets and html 0024 pages from the web. It has a memory cache for these objects. 0025 */ 0026 #ifndef _khtml_loader_h 0027 #define _khtml_loader_h 0028 0029 #include "loader_client.h" 0030 0031 #include <stdlib.h> 0032 #include <QObject> 0033 #include <QPixmap> 0034 #include <QBuffer> 0035 #include <QStringList> 0036 #include <QTextCodec> 0037 #include <QTimer> 0038 #include <QSet> 0039 #include <QDateTime> 0040 #include <QLinkedList> 0041 #include <QUrl> 0042 0043 #include <kio/global.h> 0044 0045 #include <khtml_settings.h> 0046 #include <dom/dom_string.h> 0047 #include "imload/image.h" 0048 #include "imload/imageowner.h" 0049 0050 class KHTMLPart; 0051 0052 class KJob; 0053 namespace KIO 0054 { 0055 class Job; 0056 } 0057 0058 namespace DOM 0059 { 0060 class DocumentImpl; 0061 } 0062 0063 namespace khtml 0064 { 0065 class CachedObject; 0066 class Request; 0067 class DocLoader; 0068 0069 /** 0070 * @internal 0071 * 0072 * A cached object. Classes who want to use this object should derive 0073 * from CachedObjectClient, to get the function calls in case the requested data has arrived. 0074 * 0075 * This class also does the actual communication with kio and loads the file. 0076 */ 0077 class CachedObject 0078 { 0079 public: 0080 enum Type { 0081 Image, 0082 CSSStyleSheet, 0083 Script, 0084 Sound, 0085 Font 0086 }; 0087 0088 enum Status { 0089 Unknown, // let imagecache decide what to do with it 0090 New, // inserting new image 0091 Pending, // only partially loaded 0092 Persistent, // never delete this pixmap 0093 Cached // regular case 0094 }; 0095 0096 enum PreloadResult { 0097 PreloadNotReferenced = 0, 0098 PreloadReferenced, 0099 PreloadReferencedWhileLoading, 0100 PreloadReferencedWhileComplete 0101 }; 0102 0103 PreloadResult preloadResult() const 0104 { 0105 return m_preloadResult; 0106 } 0107 void setProspectiveRequest() 0108 { 0109 m_prospectiveRequest = true; 0110 } 0111 0112 CachedObject(const DOM::DOMString &url, Type type, KIO::CacheControl _cachePolicy, int size) 0113 : m_url(url), m_type(type), m_cachePolicy(_cachePolicy), 0114 m_size(size) 0115 { 0116 m_status = Pending; 0117 m_accessCount = 0; 0118 m_cachePolicy = _cachePolicy; 0119 m_request = nullptr; 0120 m_deleted = false; 0121 m_free = false; 0122 m_hadError = false; 0123 m_wasBlocked = false; 0124 m_prev = m_next = nullptr; 0125 m_preloadCount = 0; 0126 m_preloadResult = PreloadNotReferenced; 0127 m_prospectiveRequest = false; 0128 } 0129 virtual ~CachedObject(); 0130 0131 virtual void data(QBuffer &buffer, bool eof) = 0; 0132 virtual void error(int err, const char *text) = 0; 0133 0134 const DOM::DOMString &url() const 0135 { 0136 return m_url; 0137 } 0138 Type type() const 0139 { 0140 return m_type; 0141 } 0142 0143 virtual void ref(CachedObjectClient *consumer); 0144 virtual void deref(CachedObjectClient *consumer); 0145 0146 int count() const 0147 { 0148 return m_clients.count(); 0149 } 0150 int accessCount() const 0151 { 0152 return m_accessCount; 0153 } 0154 0155 bool isPreloaded() const 0156 { 0157 return m_preloadCount; 0158 } 0159 void increasePreloadCount() 0160 { 0161 ++m_preloadCount; 0162 } 0163 void decreasePreloadCount() 0164 { 0165 assert(m_preloadCount); 0166 --m_preloadCount; 0167 } 0168 0169 void setStatus(Status s) 0170 { 0171 m_status = s; 0172 } 0173 Status status() const 0174 { 0175 return m_status; 0176 } 0177 0178 virtual void setCharset(const QString & /*charset*/) {} 0179 0180 QTextCodec *codecForBuffer(const QString &charset, const QByteArray &buffer) const; 0181 0182 int size() const 0183 { 0184 return m_size; 0185 } 0186 0187 bool isLoaded() const 0188 { 0189 return !m_loading; 0190 } 0191 bool hadError() const 0192 { 0193 return m_hadError; 0194 } 0195 0196 bool free() const 0197 { 0198 return m_free; 0199 } 0200 0201 KIO::CacheControl cachePolicy() const 0202 { 0203 return m_cachePolicy; 0204 } 0205 0206 void setRequest(Request *_request); 0207 0208 bool canDelete() const 0209 { 0210 return (m_clients.count() == 0 && !m_request && !m_preloadCount); 0211 } 0212 0213 void setExpireDate(const QDateTime &_expireDate) 0214 { 0215 m_expireDate = _expireDate; 0216 } 0217 0218 bool isExpired() const; 0219 0220 virtual void finish(); 0221 0222 /** 0223 * List of acceptable mimetypes separated by ",". A mimetype may contain a wildcard. 0224 */ 0225 // e.g. "text/*" 0226 QString accept() const 0227 { 0228 return m_accept; 0229 } 0230 void setAccept(const QString &_accept) 0231 { 0232 m_accept = _accept; 0233 } 0234 0235 // the mimetype that was eventually used 0236 QString mimetype() const 0237 { 0238 return m_mimetype; 0239 } 0240 0241 protected: 0242 void setSize(int size); 0243 QHash<CachedObjectClient *, CachedObjectClient *> m_clients; 0244 DOM::DOMString m_url; 0245 QString m_accept; 0246 QString m_mimetype; 0247 Request *m_request; 0248 Type m_type; 0249 Status m_status; 0250 int m_accessCount; 0251 KIO::CacheControl m_cachePolicy; 0252 QDateTime m_expireDate; 0253 int m_size; 0254 unsigned m_preloadCount; 0255 PreloadResult m_preloadResult: 3; 0256 bool m_deleted : 1; 0257 bool m_loading : 1; 0258 bool m_free : 1; 0259 bool m_hadError : 1; 0260 bool m_wasBlocked : 1; 0261 bool m_prospectiveRequest: 1; 0262 0263 private: 0264 bool allowInLRUList() const 0265 { 0266 return canDelete() && !m_free && status() != Persistent; 0267 } 0268 CachedObject *m_next; 0269 CachedObject *m_prev; 0270 friend class Cache; 0271 friend class ::KHTMLPart; 0272 friend class Loader; 0273 }; 0274 0275 bool isAcceptableCSSMimetype(const DOM::DOMString &mimetype); 0276 0277 /** 0278 * a cached style sheet. also used for loading xml documents. 0279 * 0280 * ### rename to CachedTextDoc or something since it's more generic than just for css 0281 */ 0282 class CachedCSSStyleSheet : public CachedObject 0283 { 0284 public: 0285 CachedCSSStyleSheet(DocLoader *dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, 0286 const char *accept); 0287 CachedCSSStyleSheet(const DOM::DOMString &url, const QString &stylesheet_data); 0288 0289 const DOM::DOMString &sheet() const 0290 { 0291 return m_sheet; 0292 } 0293 0294 void ref(CachedObjectClient *consumer) override; 0295 0296 void data(QBuffer &buffer, bool eof) override; 0297 void error(int err, const char *text) override; 0298 0299 void setCharsetHint(const QString &charset) 0300 { 0301 m_charsetHint = charset; 0302 } 0303 void setCharset(const QString &charset) override 0304 { 0305 m_charset = charset; 0306 } 0307 QString checkCharset(const QByteArray &buffer) const; 0308 0309 protected: 0310 void checkNotify(); 0311 0312 DOM::DOMString m_sheet; 0313 QString m_charset; 0314 QString m_charsetHint; 0315 int m_err; 0316 QString m_errText; 0317 }; 0318 0319 /** 0320 * a cached script 0321 */ 0322 class CachedScript : public CachedObject 0323 { 0324 public: 0325 CachedScript(DocLoader *dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, const char *accept); 0326 CachedScript(const DOM::DOMString &url, const QString &script_data); 0327 0328 const DOM::DOMString &script() const 0329 { 0330 return m_script; 0331 } 0332 0333 void ref(CachedObjectClient *consumer) override; 0334 0335 void data(QBuffer &buffer, bool eof) override; 0336 void error(int err, const char *text) override; 0337 0338 void checkNotify(); 0339 0340 bool isLoaded() const 0341 { 0342 return !m_loading; 0343 } 0344 void setCharset(const QString &charset) override 0345 { 0346 m_charset = charset; 0347 } 0348 0349 protected: 0350 QString m_charset; 0351 DOM::DOMString m_script; 0352 }; 0353 0354 class ImageSource; 0355 0356 /** 0357 * a cached image 0358 */ 0359 class CachedImage : public QObject, public CachedObject, public khtmlImLoad::ImageOwner 0360 { 0361 Q_OBJECT 0362 public: 0363 CachedImage(DocLoader *dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, const char *accept); 0364 virtual ~CachedImage(); 0365 0366 QPixmap pixmap() const; 0367 QPixmap *scaled_pixmap(int xWidth, int xHeight); 0368 QPixmap tiled_pixmap(const QColor &bg, int xWidth = -1, int xHeight = -1); 0369 0370 QSize pixmap_size() const; // returns the size of the complete (i.e. when finished) loading 0371 //QRect valid_rect() const; // returns the rectangle of pixmap that has been loaded already 0372 0373 bool canRender() const 0374 { 0375 return !isErrorImage() && pixmap_size().width() > 0 && pixmap_size().height() > 0; 0376 } 0377 void ref(CachedObjectClient *consumer) override; 0378 void deref(CachedObjectClient *consumer) override; 0379 0380 void data(QBuffer &buffer, bool eof) override; 0381 void error(int err, const char *text) override; 0382 0383 bool isComplete() const 0384 { 0385 return i && i->complete(); 0386 } 0387 bool isTransparent() const 0388 { 0389 return false; 0390 } //### isFullyTransparent; } 0391 bool isErrorImage() const 0392 { 0393 return m_hadError; 0394 } 0395 bool isBlockedImage() const 0396 { 0397 return m_wasBlocked; 0398 } 0399 const QString &suggestedFilename() const 0400 { 0401 return m_suggestedFilename; 0402 } 0403 void setSuggestedFilename(const QString &s) 0404 { 0405 m_suggestedFilename = s; 0406 } 0407 #ifdef IMAGE_TITLES 0408 const QString &suggestedTitle() const 0409 { 0410 return m_suggestedTitle; 0411 } 0412 void setSuggestedTitle(const QString &s) 0413 { 0414 m_suggestedTitle = s; 0415 } 0416 #else 0417 const QString &suggestedTitle() const 0418 { 0419 return m_suggestedFilename; 0420 } 0421 #endif 0422 0423 void setShowAnimations(KHTMLSettings::KAnimationAdvice); 0424 0425 void finish() override; 0426 0427 khtmlImLoad::Image *image() 0428 { 0429 return i; 0430 } 0431 0432 protected: 0433 void clear(); 0434 0435 private: 0436 /** 0437 Interface to the image 0438 */ 0439 void imageHasGeometry(khtmlImLoad::Image *img, int width, int height) override; 0440 void imageChange(khtmlImLoad::Image *img, QRect region) override; 0441 void imageError(khtmlImLoad::Image *img) override; 0442 void imageDone(khtmlImLoad::Image *img) override; 0443 private: 0444 void doNotifyFinished(); 0445 0446 void do_notify(const QRect &r); 0447 khtmlImLoad::Image *i; 0448 0449 QString m_suggestedFilename; 0450 #ifdef IMAGE_TITLES 0451 QString m_suggestedTitle; 0452 #endif 0453 QPixmap *bg; 0454 QPixmap *scaled; 0455 QRgb bgColor; 0456 QSize bgSize; 0457 0458 friend class Cache; 0459 friend class ::KHTMLPart; 0460 }; 0461 0462 /** 0463 * a cached sound 0464 */ 0465 class CachedSound : public CachedObject 0466 { 0467 public: 0468 CachedSound(DocLoader *dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, const char *accept); 0469 0470 QByteArray sound() const 0471 { 0472 return m_sound; 0473 } 0474 0475 void ref(CachedObjectClient *consumer) override; 0476 void data(QBuffer &buffer, bool eof) override; 0477 void error(int err, const char *text) override; 0478 0479 void checkNotify(); 0480 0481 bool isLoaded() const 0482 { 0483 return !m_loading; 0484 } 0485 0486 protected: 0487 QByteArray m_sound; 0488 }; 0489 0490 /** 0491 * a cached font 0492 */ 0493 class CachedFont : public CachedObject 0494 { 0495 public: 0496 CachedFont(DocLoader *dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, const char *accept); 0497 0498 QByteArray font() const 0499 { 0500 return m_font; 0501 } 0502 0503 void ref(CachedObjectClient *consumer) override; 0504 void data(QBuffer &buffer, bool eof) override; 0505 void error(int err, const char *text) override; 0506 0507 void checkNotify(); 0508 0509 bool isLoaded() const 0510 { 0511 return !m_loading; 0512 } 0513 0514 protected: 0515 QByteArray m_font; 0516 }; 0517 0518 /** 0519 * @internal 0520 * 0521 * Manages the loading of scripts/images/stylesheets for a particular document 0522 */ 0523 class DocLoader 0524 { 0525 public: 0526 DocLoader(KHTMLPart *, DOM::DocumentImpl *); 0527 ~DocLoader(); 0528 0529 CachedImage *requestImage(const DOM::DOMString &url); 0530 CachedCSSStyleSheet *requestStyleSheet(const DOM::DOMString &url, const QString &charsetHint, 0531 const char *accept = "text/css", bool userSheet = false); 0532 CachedScript *requestScript(const DOM::DOMString &url, const QString &charset); 0533 CachedSound *requestSound(const DOM::DOMString &url); 0534 CachedFont *requestFont(const DOM::DOMString &url); 0535 bool willLoadMediaElement(const DOM::DOMString &url); 0536 0537 bool autoloadImages() const 0538 { 0539 return m_bautoloadImages; 0540 } 0541 KIO::CacheControl cachePolicy() const 0542 { 0543 return m_cachePolicy; 0544 } 0545 KHTMLSettings::KAnimationAdvice showAnimations() const 0546 { 0547 return m_showAnimations; 0548 } 0549 QDateTime expireDate() const 0550 { 0551 return m_expireDate; 0552 } 0553 KHTMLPart *part() const 0554 { 0555 return m_part; 0556 } 0557 DOM::DocumentImpl *doc() const 0558 { 0559 return m_doc; 0560 } 0561 0562 void setCacheCreationDate(const QDateTime &); 0563 void setExpireDate(const QDateTime &); 0564 void setRelativeExpireDate(qint64 seconds); 0565 void setAutoloadImages(bool); 0566 void setCachePolicy(KIO::CacheControl cachePolicy) 0567 { 0568 m_cachePolicy = cachePolicy; 0569 } 0570 void setShowAnimations(KHTMLSettings::KAnimationAdvice); 0571 void insertCachedObject(CachedObject *o) const; 0572 void removeCachedObject(CachedObject *o) const 0573 { 0574 m_docObjects.remove(o); 0575 } 0576 void clearPreloads(); 0577 void registerPreload(CachedObject *); 0578 void printPreloadStats(); 0579 0580 private: 0581 bool needReload(CachedObject *existing, const QString &fullUrl); 0582 0583 friend class Cache; 0584 friend class DOM::DocumentImpl; 0585 friend class ::KHTMLPart; 0586 0587 QStringList m_reloadedURLs; 0588 mutable QSet<CachedObject *> m_docObjects; 0589 QSet<CachedObject *> m_preloads; 0590 QDateTime m_expireDate; 0591 QDateTime m_creationDate; 0592 KIO::CacheControl m_cachePolicy; 0593 bool m_bautoloadImages : 1; 0594 KHTMLSettings::KAnimationAdvice m_showAnimations : 2; 0595 KHTMLPart *m_part; 0596 DOM::DocumentImpl *m_doc; 0597 }; 0598 0599 /** 0600 * @internal 0601 */ 0602 class Request 0603 { 0604 public: 0605 Request(DocLoader *dl, CachedObject *_object, bool _incremental, int priority); 0606 ~Request(); 0607 bool incremental; 0608 int priority; // -10 to 10, smaller values mean higher priority 0609 QBuffer m_buffer; 0610 CachedObject *object; 0611 DocLoader *m_docLoader; 0612 }; 0613 0614 /** 0615 * @internal 0616 */ 0617 class Loader : public QObject 0618 { 0619 0620 Q_OBJECT 0621 0622 public: 0623 Loader(); 0624 ~Loader(); 0625 0626 void load(DocLoader *dl, CachedObject *object, bool incremental = true, int priority = 0); 0627 0628 int numRequests(DocLoader *dl) const; 0629 void cancelRequests(DocLoader *dl); 0630 0631 // may return 0L 0632 KIO::Job *jobForRequest(const DOM::DOMString &url) const; 0633 0634 Q_SIGNALS: 0635 void requestStarted(khtml::DocLoader *dl, khtml::CachedObject *obj); 0636 void requestDone(khtml::DocLoader *dl, khtml::CachedObject *obj); 0637 void requestFailed(khtml::DocLoader *dl, khtml::CachedObject *obj); 0638 0639 protected Q_SLOTS: 0640 void slotFinished(KJob *); 0641 void slotMimetype(KIO::Job *, const QString &s); 0642 void slotData(KIO::Job *, const QByteArray &); 0643 0644 protected: 0645 void scheduleRequest(Request *req); 0646 QHash<KIO::Job *, Request *> m_requestsLoading; 0647 QStringList m_supportedImageTypes; 0648 }; 0649 0650 /** 0651 * @internal 0652 * 0653 * Provides a cache/loader for objects needed for displaying the html page. 0654 * At the moment these are stylesheets, scripts and images 0655 */ 0656 class Cache 0657 { 0658 friend class DocLoader; 0659 0660 template<typename CachedObjectType, enum CachedObject::Type CachedType> 0661 static CachedObjectType *requestObject(DocLoader *dl, const QUrl &kurl, const char *accept); 0662 0663 public: 0664 /** 0665 * init the cache in case it's not already. This needs to get called once 0666 * before using it. 0667 */ 0668 KHTML_EXPORT static void init(); 0669 0670 /** 0671 * Ask the cache for some url. Will return a cachedObject, and 0672 * load the requested data in case it's not cached 0673 * if the DocLoader is zero, the url must be full-qualified. 0674 * Otherwise, it is automatically base-url expanded 0675 */ 0676 // static CachedImage *requestImage(const QUrl& url) 0677 // { return Cache::requestObject<CachedImage, CachedObject::Image>( 0, url, 0 ); } 0678 0679 /** 0680 * Pre-loads a stylesheet into the cache. 0681 */ 0682 static void preloadStyleSheet(const QString &url, const QString &stylesheet_data); 0683 0684 /** 0685 * Pre-loads a script into the cache. 0686 */ 0687 static void preloadScript(const QString &url, const QString &script_data); 0688 0689 static void setSize(int bytes); 0690 static int size() 0691 { 0692 return maxSize; 0693 } 0694 static void statistics(); 0695 KHTML_EXPORT static void flush(bool force = false); 0696 0697 /** 0698 * clears the cache 0699 * Warning: call this only at the end of your program, to clean 0700 * up memory (useful for finding memory holes) 0701 */ 0702 KHTML_EXPORT static void clear(); 0703 0704 static Loader *loader() 0705 { 0706 return m_loader; 0707 } 0708 0709 static QPixmap *nullPixmap; 0710 static QPixmap *brokenPixmap; 0711 static QPixmap *blockedPixmap; 0712 static int cacheSize; 0713 0714 static void removeCacheEntry(CachedObject *object); 0715 0716 private: 0717 0718 static void checkLRUAndUncacheableListIntegrity(); 0719 0720 friend class CachedObject; 0721 0722 static QHash<QString, CachedObject *> *cache; 0723 static QLinkedList<DocLoader *> *docloader; 0724 static QLinkedList<CachedObject *> *freeList; 0725 static void insertInLRUList(CachedObject *); 0726 static void removeFromLRUList(CachedObject *); 0727 0728 static int totalSizeOfLRU; 0729 static int maxSize; 0730 0731 static Loader *m_loader; 0732 }; 0733 0734 } // namespace 0735 0736 #endif