File indexing completed on 2024-04-21 14:58:51

0001 /* This file is part of the KDE project
0002  *
0003  * Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
0004  * Copyright (C) 2007 David Faure <faure@kde.org>
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Library General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Library General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Library General Public License
0017  * along with this library; see the file COPYING.LIB.  If not, write to
0018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020  */
0021 
0022 #include "khtml_global.h"
0023 #include "khtml_part.h"
0024 #include "khtml_settings.h"
0025 #include "../khtml_version.h"
0026 
0027 #include "css/cssstyleselector.h"
0028 #include "css/css_mediaquery.h"
0029 #include "html/html_imageimpl.h"
0030 #include "rendering/render_style.h"
0031 #include "rendering/break_lines.h"
0032 #include "misc/htmlnames.h"
0033 #include "misc/loader.h"
0034 #include "misc/arena.h"
0035 #include "misc/paintbuffer.h"
0036 
0037 #include <QLinkedList>
0038 
0039 #include <kiconloader.h>
0040 #include <kaboutdata.h>
0041 #include <klocalizedstring.h>
0042 
0043 #include <assert.h>
0044 
0045 #include "khtml_debug.h"
0046 
0047 // SVG
0048 #include "svg/SVGNames.h"
0049 
0050 KHTMLGlobal *KHTMLGlobal::s_self = nullptr;
0051 unsigned long int KHTMLGlobal::s_refcnt = 0;
0052 KIconLoader *KHTMLGlobal::s_iconLoader = nullptr;
0053 KAboutData *KHTMLGlobal::s_about = nullptr;
0054 KHTMLSettings *KHTMLGlobal::s_settings = nullptr;
0055 
0056 static QLinkedList<KHTMLPart *> *s_parts = nullptr;
0057 static QLinkedList<DOM::DocumentImpl *> *s_docs = nullptr;
0058 
0059 KHTMLGlobal::KHTMLGlobal()
0060 {
0061     assert(!s_self);
0062     s_self = this;
0063     ref();
0064 
0065     khtml::Cache::init();
0066 
0067     khtml::NamespaceFactory::initIdTable();
0068     khtml::PrefixFactory::initIdTable();
0069     khtml::LocalNameFactory::initIdTable();
0070     DOM::emptyLocalName = DOM::LocalName::fromId(0);
0071     DOM::emptyPrefixName = DOM::PrefixName::fromId(0);
0072     DOM::emptyNamespaceName = DOM::NamespaceName::fromId(DOM::emptyNamespace);
0073     WebCore::SVGNames::init();
0074 }
0075 
0076 KHTMLGlobal::~KHTMLGlobal()
0077 {
0078     //qCDebug(KHTML_LOG) << this;
0079     if (s_self == this) {
0080         finalCheck();
0081         delete s_iconLoader;
0082         delete s_about;
0083         delete s_settings;
0084         delete KHTMLSettings::avFamilies;
0085         if (s_parts) {
0086             assert(s_parts->isEmpty());
0087             delete s_parts;
0088         }
0089         if (s_docs) {
0090             assert(s_docs->isEmpty());
0091             delete s_docs;
0092         }
0093 
0094         s_iconLoader = nullptr;
0095         s_about = nullptr;
0096         s_settings = nullptr;
0097         s_parts = nullptr;
0098         s_docs = nullptr;
0099         KHTMLSettings::avFamilies = nullptr;
0100 
0101         // clean up static data
0102         khtml::CSSStyleSelector::clear();
0103         khtml::RenderStyle::cleanup();
0104         khtml::RenderObject::cleanup();
0105         khtml::PaintBuffer::cleanup();
0106         khtml::MediaQueryEvaluator::cleanup();
0107         khtml::Cache::clear();
0108         khtml::cleanup_thaibreaks();
0109         khtml::ArenaFinish();
0110     } else {
0111         deref();
0112     }
0113 }
0114 
0115 void KHTMLGlobal::ref()
0116 {
0117     if (!s_refcnt && !s_self) {
0118         //qCDebug(KHTML_LOG) << "Creating KHTMLGlobal instance";
0119         // we can't use a staticdeleter here, because that would mean
0120         // that the KHTMLGlobal instance gets deleted from within a qPostRoutine, called
0121         // from the QApplication destructor. That however is too late, because
0122         // we want to destruct a KComponentData object, which involves destructing
0123         // a KConfig object, which might call KGlobal::dirs() (in sync()) which
0124         // probably is not going to work ;-)
0125         // well, perhaps I'm wrong here, but as I'm unsure I try to stay on the
0126         // safe side ;-) -> let's use a simple reference counting scheme
0127         // (Simon)
0128         new KHTMLGlobal; // does initial ref()
0129     } else {
0130         ++s_refcnt;
0131     }
0132     //qCDebug(KHTML_LOG) << "s_refcnt=" << s_refcnt;
0133 }
0134 
0135 void KHTMLGlobal::deref()
0136 {
0137     //qCDebug(KHTML_LOG) << "s_refcnt=" << s_refcnt - 1;
0138     if (!--s_refcnt && s_self) {
0139         delete s_self;
0140         s_self = nullptr;
0141     }
0142 }
0143 
0144 void KHTMLGlobal::registerPart(KHTMLPart *part)
0145 {
0146     //qCDebug(KHTML_LOG) << part;
0147     if (!s_parts) {
0148         s_parts = new QLinkedList<KHTMLPart *>;
0149     }
0150 
0151     if (!s_parts->contains(part)) {
0152         s_parts->append(part);
0153         ref();
0154     }
0155 }
0156 
0157 void KHTMLGlobal::deregisterPart(KHTMLPart *part)
0158 {
0159     //qCDebug(KHTML_LOG) << part;
0160     assert(s_parts);
0161 
0162     if (s_parts->removeAll(part)) {
0163         if (s_parts->isEmpty()) {
0164             delete s_parts;
0165             s_parts = nullptr;
0166         }
0167         deref();
0168     }
0169 }
0170 
0171 void KHTMLGlobal::registerDocumentImpl(DOM::DocumentImpl *doc)
0172 {
0173     //qCDebug(KHTML_LOG) << doc;
0174     if (!s_docs) {
0175         s_docs = new QLinkedList<DOM::DocumentImpl *>;
0176     }
0177 
0178     if (!s_docs->contains(doc)) {
0179         s_docs->append(doc);
0180         ref();
0181     }
0182 }
0183 
0184 void KHTMLGlobal::deregisterDocumentImpl(DOM::DocumentImpl *doc)
0185 {
0186     //qCDebug(KHTML_LOG) << doc;
0187     assert(s_docs);
0188 
0189     if (s_docs->removeAll(doc)) {
0190         if (s_docs->isEmpty()) {
0191             delete s_docs;
0192             s_docs = nullptr;
0193         }
0194         deref();
0195     }
0196 }
0197 
0198 const KAboutData &KHTMLGlobal::aboutData()
0199 {
0200     assert(s_self);
0201 
0202     if (!s_about) {
0203         s_about = new KAboutData("khtml", i18n("KHTML"), QStringLiteral(KHTML_VERSION_STRING),
0204                                  i18n("Embeddable HTML component"),
0205                                  KAboutLicense::LGPL);
0206         s_about->addAuthor(QStringLiteral("Lars Knoll"), QString(), "knoll@kde.org");
0207         s_about->addAuthor(QStringLiteral("Antti Koivisto"), QString(), "koivisto@kde.org");
0208         s_about->addAuthor(QStringLiteral("Waldo Bastian"), QString(), "bastian@kde.org");
0209         s_about->addAuthor(QStringLiteral("Dirk Mueller"), QString(), "mueller@kde.org");
0210         s_about->addAuthor(QStringLiteral("Peter Kelly"), QString(), "pmk@kde.org");
0211         s_about->addAuthor(QStringLiteral("Torben Weis"), QString(), "weis@kde.org");
0212         s_about->addAuthor(QStringLiteral("Martin Jones"), QString(), "mjones@kde.org");
0213         s_about->addAuthor(QStringLiteral("Simon Hausmann"), QString(), "hausmann@kde.org");
0214         s_about->addAuthor(QStringLiteral("Tobias Anton"), QString(), "anton@stud.fbi.fh-darmstadt.de");
0215 
0216     }
0217 
0218     return *s_about;
0219 }
0220 
0221 KIconLoader *KHTMLGlobal::iconLoader()
0222 {
0223     if (!s_iconLoader) {
0224         s_iconLoader = new KIconLoader(aboutData().componentName());
0225     }
0226 
0227     return s_iconLoader;
0228 }
0229 
0230 KHTMLSettings *KHTMLGlobal::defaultHTMLSettings()
0231 {
0232     assert(s_self);
0233     if (!s_settings) {
0234         s_settings = new KHTMLSettings();
0235     }
0236 
0237     return s_settings;
0238 }
0239 
0240 void KHTMLGlobal::finalCheck()
0241 {
0242 #ifndef NDEBUG
0243     if (s_refcnt) {
0244         if (s_parts && !s_parts->isEmpty()) {
0245             Q_FOREACH (KHTMLPart *part, *s_parts) {
0246                 qCWarning(KHTML_LOG) << "Part" << part->url() << "was not deleted";
0247             }
0248         }
0249         if (s_docs && !s_docs->isEmpty()) {
0250             Q_FOREACH (DOM::DocumentImpl *doc, *s_docs) {
0251                 qCWarning(KHTML_LOG) << "Document" << doc->URL() << "was not deleted";
0252             }
0253         }
0254     }
0255 #endif
0256 }