1 /* This file is part of the KDE project
2 *
3 * Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
4 * Copyright (C) 2007 David Faure <faure@kde.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include "khtml_global.h"
23 #include "khtml_part.h"
24 #include "khtml_settings.h"
25 #include "../khtml_version.h"
26
27 #include "css/cssstyleselector.h"
28 #include "css/css_mediaquery.h"
29 #include "html/html_imageimpl.h"
30 #include "rendering/render_style.h"
31 #include "rendering/break_lines.h"
32 #include "misc/htmlnames.h"
33 #include "misc/loader.h"
34 #include "misc/arena.h"
35 #include "misc/paintbuffer.h"
36
37 #include <QLinkedList>
38
39 #include <kiconloader.h>
40 #include <kaboutdata.h>
41 #include <klocalizedstring.h>
42
43 #include <assert.h>
44
45 #include "khtml_debug.h"
46
47 // SVG
48 #include "svg/SVGNames.h"
49
50 KHTMLGlobal *KHTMLGlobal::s_self = nullptr;
51 unsigned long int KHTMLGlobal::s_refcnt = 0;
52 KIconLoader *KHTMLGlobal::s_iconLoader = nullptr;
53 KAboutData *KHTMLGlobal::s_about = nullptr;
54 KHTMLSettings *KHTMLGlobal::s_settings = nullptr;
55
56 static QLinkedList<KHTMLPart *> *s_parts = nullptr;
57 static QLinkedList<DOM::DocumentImpl *> *s_docs = nullptr;
58
KHTMLGlobal()59 KHTMLGlobal::KHTMLGlobal()
60 {
61 assert(!s_self);
62 s_self = this;
63 ref();
64
65 khtml::Cache::init();
66
67 khtml::NamespaceFactory::initIdTable();
68 khtml::PrefixFactory::initIdTable();
69 khtml::LocalNameFactory::initIdTable();
70 DOM::emptyLocalName = DOM::LocalName::fromId(0);
71 DOM::emptyPrefixName = DOM::PrefixName::fromId(0);
72 DOM::emptyNamespaceName = DOM::NamespaceName::fromId(DOM::emptyNamespace);
73 WebCore::SVGNames::init();
74 }
75
~KHTMLGlobal()76 KHTMLGlobal::~KHTMLGlobal()
77 {
78 //qCDebug(KHTML_LOG) << this;
79 if (s_self == this) {
80 finalCheck();
81 delete s_iconLoader;
82 delete s_about;
83 delete s_settings;
84 delete KHTMLSettings::avFamilies;
85 if (s_parts) {
86 assert(s_parts->isEmpty());
87 delete s_parts;
88 }
89 if (s_docs) {
90 assert(s_docs->isEmpty());
91 delete s_docs;
92 }
93
94 s_iconLoader = nullptr;
95 s_about = nullptr;
96 s_settings = nullptr;
97 s_parts = nullptr;
98 s_docs = nullptr;
99 KHTMLSettings::avFamilies = nullptr;
100
101 // clean up static data
102 khtml::CSSStyleSelector::clear();
103 khtml::RenderStyle::cleanup();
104 khtml::RenderObject::cleanup();
105 khtml::PaintBuffer::cleanup();
106 khtml::MediaQueryEvaluator::cleanup();
107 khtml::Cache::clear();
108 khtml::cleanup_thaibreaks();
109 khtml::ArenaFinish();
110 } else {
111 deref();
112 }
113 }
114
ref()115 void KHTMLGlobal::ref()
116 {
117 if (!s_refcnt && !s_self) {
118 //qCDebug(KHTML_LOG) << "Creating KHTMLGlobal instance";
119 // we can't use a staticdeleter here, because that would mean
120 // that the KHTMLGlobal instance gets deleted from within a qPostRoutine, called
121 // from the QApplication destructor. That however is too late, because
122 // we want to destruct a KComponentData object, which involves destructing
123 // a KConfig object, which might call KGlobal::dirs() (in sync()) which
124 // probably is not going to work ;-)
125 // well, perhaps I'm wrong here, but as I'm unsure I try to stay on the
126 // safe side ;-) -> let's use a simple reference counting scheme
127 // (Simon)
128 new KHTMLGlobal; // does initial ref()
129 } else {
130 ++s_refcnt;
131 }
132 //qCDebug(KHTML_LOG) << "s_refcnt=" << s_refcnt;
133 }
134
deref()135 void KHTMLGlobal::deref()
136 {
137 //qCDebug(KHTML_LOG) << "s_refcnt=" << s_refcnt - 1;
138 if (!--s_refcnt && s_self) {
139 delete s_self;
140 s_self = nullptr;
141 }
142 }
143
registerPart(KHTMLPart * part)144 void KHTMLGlobal::registerPart(KHTMLPart *part)
145 {
146 //qCDebug(KHTML_LOG) << part;
147 if (!s_parts) {
148 s_parts = new QLinkedList<KHTMLPart *>;
149 }
150
151 if (!s_parts->contains(part)) {
152 s_parts->append(part);
153 ref();
154 }
155 }
156
deregisterPart(KHTMLPart * part)157 void KHTMLGlobal::deregisterPart(KHTMLPart *part)
158 {
159 //qCDebug(KHTML_LOG) << part;
160 assert(s_parts);
161
162 if (s_parts->removeAll(part)) {
163 if (s_parts->isEmpty()) {
164 delete s_parts;
165 s_parts = nullptr;
166 }
167 deref();
168 }
169 }
170
registerDocumentImpl(DOM::DocumentImpl * doc)171 void KHTMLGlobal::registerDocumentImpl(DOM::DocumentImpl *doc)
172 {
173 //qCDebug(KHTML_LOG) << doc;
174 if (!s_docs) {
175 s_docs = new QLinkedList<DOM::DocumentImpl *>;
176 }
177
178 if (!s_docs->contains(doc)) {
179 s_docs->append(doc);
180 ref();
181 }
182 }
183
deregisterDocumentImpl(DOM::DocumentImpl * doc)184 void KHTMLGlobal::deregisterDocumentImpl(DOM::DocumentImpl *doc)
185 {
186 //qCDebug(KHTML_LOG) << doc;
187 assert(s_docs);
188
189 if (s_docs->removeAll(doc)) {
190 if (s_docs->isEmpty()) {
191 delete s_docs;
192 s_docs = nullptr;
193 }
194 deref();
195 }
196 }
197
aboutData()198 const KAboutData &KHTMLGlobal::aboutData()
199 {
200 assert(s_self);
201
202 if (!s_about) {
203 s_about = new KAboutData("khtml", i18n("KHTML"), QStringLiteral(KHTML_VERSION_STRING),
204 i18n("Embeddable HTML component"),
205 KAboutLicense::LGPL);
206 s_about->addAuthor(QStringLiteral("Lars Knoll"), QString(), "knoll@kde.org");
207 s_about->addAuthor(QStringLiteral("Antti Koivisto"), QString(), "koivisto@kde.org");
208 s_about->addAuthor(QStringLiteral("Waldo Bastian"), QString(), "bastian@kde.org");
209 s_about->addAuthor(QStringLiteral("Dirk Mueller"), QString(), "mueller@kde.org");
210 s_about->addAuthor(QStringLiteral("Peter Kelly"), QString(), "pmk@kde.org");
211 s_about->addAuthor(QStringLiteral("Torben Weis"), QString(), "weis@kde.org");
212 s_about->addAuthor(QStringLiteral("Martin Jones"), QString(), "mjones@kde.org");
213 s_about->addAuthor(QStringLiteral("Simon Hausmann"), QString(), "hausmann@kde.org");
214 s_about->addAuthor(QStringLiteral("Tobias Anton"), QString(), "anton@stud.fbi.fh-darmstadt.de");
215
216 }
217
218 return *s_about;
219 }
220
iconLoader()221 KIconLoader *KHTMLGlobal::iconLoader()
222 {
223 if (!s_iconLoader) {
224 s_iconLoader = new KIconLoader(aboutData().componentName());
225 }
226
227 return s_iconLoader;
228 }
229
defaultHTMLSettings()230 KHTMLSettings *KHTMLGlobal::defaultHTMLSettings()
231 {
232 assert(s_self);
233 if (!s_settings) {
234 s_settings = new KHTMLSettings();
235 }
236
237 return s_settings;
238 }
239
finalCheck()240 void KHTMLGlobal::finalCheck()
241 {
242 #ifndef NDEBUG
243 if (s_refcnt) {
244 if (s_parts && !s_parts->isEmpty()) {
245 Q_FOREACH (KHTMLPart *part, *s_parts) {
246 qCWarning(KHTML_LOG) << "Part" << part->url() << "was not deleted";
247 }
248 }
249 if (s_docs && !s_docs->isEmpty()) {
250 Q_FOREACH (DOM::DocumentImpl *doc, *s_docs) {
251 qCWarning(KHTML_LOG) << "Document" << doc->URL() << "was not deleted";
252 }
253 }
254 }
255 #endif
256 }
257