KHtml

html_documentimpl.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll ([email protected])
5  * (C) 1999 Antti Koivisto ([email protected])
6  * (C) 2010 Maksim Orlovich ([email protected])
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., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24 
25 #include "html/html_documentimpl.h"
26 #include "html/html_imageimpl.h"
27 #include "html/html_headimpl.h"
28 #include "html/html_baseimpl.h"
29 #include "html/htmltokenizer.h"
30 #include "html/html_formimpl.h"
31 
32 #include "khtmlview.h"
33 #include "khtml_part.h"
34 #include "khtmlpart_p.h"
35 #include "khtml_settings.h"
36 
37 #include "xml/xml_tokenizer.h"
38 #include "xml/dom2_eventsimpl.h"
39 
40 #include <khtml_global.h>
41 #include "rendering/render_object.h"
42 #include "dom/dom_exception.h"
43 
44 #include "khtml_debug.h"
45 #include <QDBusConnection>
46 #include <kcookiejar_interface.h>
47 
48 #include "css/cssproperties.h"
49 #include "css/cssstyleselector.h"
50 #include "css/css_stylesheetimpl.h"
51 #include <stdlib.h>
52 
53 using namespace DOM;
54 using namespace khtml;
55 
56 HTMLDocumentImpl::HTMLDocumentImpl(KHTMLView *v)
57  : DocumentImpl(v)
58 {
59 // qCDebug(KHTML_LOG) << "HTMLDocumentImpl constructor this = " << this;
60  htmlElement = nullptr;
61 
62  m_doAutoFill = false;
63  m_determineParseMode = false;
64 
65  /* dynamic history stuff to be fixed later (pfeiffer)
66  connect( KHTMLGlobal::vLinks(), SIGNAL(removed(QString)),
67  SLOT(slotHistoryChanged()));
68  */
69  connect(KHTMLGlobal::vLinks(), SIGNAL(inserted(QString)),
70  SLOT(slotHistoryChanged()));
71  connect(KHTMLGlobal::vLinks(), SIGNAL(cleared()),
72  SLOT(slotHistoryChanged()));
73 }
74 
75 HTMLDocumentImpl::~HTMLDocumentImpl()
76 {
77 }
78 
79 DOMString HTMLDocumentImpl::referrer() const
80 {
81  if (part()) {
82  return part()->pageReferrer();
83  }
84  return DOMString();
85 }
86 
87 DOMString HTMLDocumentImpl::lastModified() const
88 {
89  if (part()) {
90  return part()->lastModified();
91  }
92  return DOMString();
93 }
94 
95 DOMString HTMLDocumentImpl::cookie() const
96 {
97  WId windowId = 0;
98  KHTMLView *v = view();
99 
100  if (v && v->topLevelWidget()) {
101  windowId = v->topLevelWidget()->winId();
102  }
103 
104  org::kde::KCookieServer kcookiejar("org.kde.kded5", "/modules/kcookiejar", QDBusConnection::sessionBus());
105  QDBusReply<QString> reply = kcookiejar.findDOMCookies(URL().url(), qlonglong(windowId));
106 
107  if (!reply.isValid()) {
108  qCWarning(KHTML_LOG) << "Can't communicate with cookiejar!";
109  return DOMString();
110  }
111 
112  return DOMString(reply.value());
113 }
114 
115 void HTMLDocumentImpl::setCookie(const DOMString &value)
116 {
117  WId windowId = 0;
118  KHTMLView *v = view();
119 
120  if (v && v->topLevelWidget()) {
121  windowId = v->topLevelWidget()->winId();
122  }
123 
124  QByteArray fake_header("Set-Cookie: ");
125  fake_header.append(value.string().toLatin1().constData());
126  fake_header.append("\n");
127  // Note that kded modules are autoloaded so we don't need to call loadModule ourselves.
128  org::kde::KCookieServer kcookiejar("org.kde.kded5", "/modules/kcookiejar", QDBusConnection::sessionBus());
129  // Can't use kcookiejar.addCookies because then we can't pass NoBlock...
130  kcookiejar.call(QDBus::NoBlock, "addCookies",
131  URL().url(), fake_header, qlonglong(windowId));
132 }
133 
134 void HTMLDocumentImpl::setBody(HTMLElementImpl *_body, int &exceptioncode)
135 {
136  HTMLElementImpl *b = body();
137  if (!_body) {
138  exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
139  return;
140  }
141  if (!b) {
142  documentElement()->appendChild(_body, exceptioncode);
143  } else {
144  documentElement()->replaceChild(_body, b, exceptioncode);
145  }
146 }
147 
148 Tokenizer *HTMLDocumentImpl::createTokenizer()
149 {
150  return new HTMLTokenizer(docPtr(), m_view);
151 }
152 
153 // --------------------------------------------------------------------------
154 // not part of the DOM
155 // --------------------------------------------------------------------------
156 
157 bool HTMLDocumentImpl::childAllowed(NodeImpl *newChild)
158 {
159  // ### support comments. etc as a child
160  return (newChild->id() == ID_HTML || newChild->id() == ID_COMMENT || newChild->nodeType() == Node::DOCUMENT_TYPE_NODE);
161 }
162 
163 ElementImpl *HTMLDocumentImpl::createElement(const DOMString &name, int *pExceptioncode)
164 {
165  if (pExceptioncode && !Element::khtmlValidQualifiedName(name)) {
166  *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
167  return nullptr;
168  }
169 
170  return createHTMLElement(name, hMode != XHtml);
171 }
172 
173 ElementImpl *HTMLDocumentImpl::activeElement() const
174 {
175  NodeImpl *fn = focusNode();
176  if (!fn || !fn->isElementNode()) {
177  return body();
178  } else {
179  return static_cast<ElementImpl *>(fn);
180  }
181 }
182 
183 void HTMLDocumentImpl::slotHistoryChanged()
184 {
185  if (true || !m_render) {
186  return;
187  }
188 
189  recalcStyle(Force);
190  m_render->repaint();
191 }
192 
193 HTMLMapElementImpl *HTMLDocumentImpl::getMap(const DOMString &_url)
194 {
195  QString url = _url.string();
196  QString s;
197  int pos = url.indexOf('#');
198  //qCDebug(KHTML_LOG) << "map pos of #:" << pos;
199  s = QString(_url.unicode() + pos + 1, _url.length() - pos - 1);
200 
202 
203  if (it != mapMap.constEnd()) {
204  return *it;
205  } else {
206  return nullptr;
207  }
208 }
209 
210 void HTMLDocumentImpl::contentLoaded()
211 {
212  // auto fill: walk the tree and try to fill in login credentials
213  if (view() && m_doAutoFill) {
214  for (NodeImpl *n = this; n; n = n->traverseNextNode())
215  if (n->id() == ID_FORM) {
216  static_cast<HTMLFormElementImpl *>(n)->doAutoFill();
217  }
218  m_doAutoFill = false;
219  }
220 }
221 
222 void HTMLDocumentImpl::close()
223 {
224  bool doload = !parsing() && m_tokenizer;
225 
226  DocumentImpl::close();
227 
228  if (doload) {
229 
230  if (title().isEmpty()) { // ensure setTitle is called at least once
231  setTitle(DOMString());
232  }
233 
234  // According to dom the load event must not bubble
235  // but other browsers execute in a frameset document
236  // the first(IE)/last(Moz/Konq) registered onload on a <frame> and the
237  // first(IE)/last(Moz/Konq) registered onload on a <frameset>.
238 
239  //qCDebug(KHTML_LOG) << "dispatching LOAD_EVENT on document " << document() << " " << (view()?view()->part()->name():0);
240 
241  //Make sure to flush any pending image events now, as we want them out before the document's load event
242  dispatchImageLoadEventsNow();
243  document()->dispatchWindowEvent(EventImpl::LOAD_EVENT, false, false);
244 
245  // don't update rendering if we're going to redirect anyway
246  if (part() && (part()->d->m_redirectURL.isEmpty() ||
247  part()->d->m_delayRedirect > 1)) {
248  updateRendering();
249  }
250  }
251 }
252 
253 void HTMLDocumentImpl::determineParseMode()
254 {
255  m_determineParseMode = true;
256  if (m_doctype == nullptr) {
257  // Currently we haven't got any doctype, so default to quirks mode and Html4
258  changeModes(Compat, Html4);
259  }
260 }
261 
262 void HTMLDocumentImpl::changeModes(ParseMode newPMode, HTMLMode newHMode)
263 {
264  if (!m_determineParseMode) { // change mode only when KHTMLPart called determineParseMode
265  return;
266  }
267  ParseMode oldPMode = pMode;
268  pMode = newPMode;
269  hMode = newHMode;
270  // This needs to be done last, see tests/parser/compatmode_xhtml_mixed.html
271  if (hMode == Html4 && !m_htmlRequested) {
272  // this part is still debatable and possibly UA dependent
273  hMode = XHtml;
274  pMode = Transitional;
275  }
276  m_htmlCompat = (hMode != XHtml);
277 
278  m_styleSelector->strictParsing = !inCompatMode();
279 
280 #if 0
281  qCDebug(KHTML_LOG) << "DocumentImpl::determineParseMode: publicId =" << publicID << " systemId = " << systemID;
282  qCDebug(KHTML_LOG) << "DocumentImpl::determineParseMode: htmlMode = " << hMode;
283  if (pMode == Strict) {
284  qCDebug(KHTML_LOG) << " using strict parseMode";
285  } else if (pMode == Compat) {
286  qCDebug(KHTML_LOG) << " using compatibility parseMode";
287  } else {
288  qCDebug(KHTML_LOG) << " using transitional parseMode";
289  }
290 #endif
291 
292  if (pMode != oldPMode && styleSelector()) {
293  updateStyleSelector(true/*shallow*/);
294  }
295 }
296 
297 NodeListImpl *HTMLDocumentImpl::getElementsByName(const DOMString &elementName)
298 {
299  return new NameNodeListImpl(this, elementName);
300 }
301 
302 HTMLCollectionImpl *HTMLDocumentImpl::images()
303 {
304  return new HTMLCollectionImpl(this, HTMLCollectionImpl::DOC_IMAGES);
305 }
306 
307 HTMLCollectionImpl *HTMLDocumentImpl::applets()
308 {
309  return new HTMLCollectionImpl(this, HTMLCollectionImpl::DOC_APPLETS);
310 }
311 
312 HTMLCollectionImpl *HTMLDocumentImpl::links()
313 {
314  return new HTMLCollectionImpl(this, HTMLCollectionImpl::DOC_LINKS);
315 }
316 
317 HTMLCollectionImpl *HTMLDocumentImpl::forms()
318 {
319  return new HTMLCollectionImpl(this, HTMLCollectionImpl::DOC_FORMS);
320 }
321 
322 HTMLCollectionImpl *HTMLDocumentImpl::layers()
323 {
324  return new HTMLCollectionImpl(this, HTMLCollectionImpl::DOC_LAYERS);
325 }
326 
327 HTMLCollectionImpl *HTMLDocumentImpl::anchors()
328 {
329  return new HTMLCollectionImpl(this, HTMLCollectionImpl::DOC_ANCHORS);
330 }
331 
332 HTMLCollectionImpl *HTMLDocumentImpl::all()
333 {
334  return new HTMLCollectionImpl(this, HTMLCollectionImpl::DOC_ALL);
335 }
336 
337 HTMLCollectionImpl *HTMLDocumentImpl::scripts()
338 {
339  return new HTMLCollectionImpl(this, HTMLCollectionImpl::DOC_SCRIPTS);
340 }
341 
342 // --------------------------------------------------------------------------
343 // Support for displaying plaintext
344 // --------------------------------------------------------------------------
345 
346 class HTMLTextTokenizer: public khtml::Tokenizer
347 {
348 public:
349  HTMLTextTokenizer(DOM::HTMLDocumentImpl *doc): m_doc(doc)
350  {}
351 
352  void begin() override;
353  void write(const TokenizerString &str, bool appendData) override;
354 
355  void end() override
356  {
357  emit finishedParsing();
358  };
359  void finish() override
360  {
361  end();
362  };
363 
364  // We don't support any inline scripts here
365  bool isWaitingForScripts() const override
366  {
367  return false;
368  }
369  bool isExecutingScript() const override
370  {
371  return false;
372  }
373  void executeScriptsWaitingForStylesheets() override {};
374 private:
375  DOM::HTMLDocumentImpl *m_doc;
376 };
377 
378 void HTMLTextTokenizer::begin()
379 {
380  int dummy;
381  DOM::ElementImpl *html = m_doc->createElement("html", &dummy);
382  DOM::ElementImpl *head = m_doc->createElement("head", &dummy);
383  DOM::ElementImpl *body = m_doc->createElement("body", &dummy);
384  DOM::ElementImpl *pre = m_doc->createElement("pre", &dummy);
385 
386  m_doc->appendChild(html, dummy);
387  html->appendChild(head, dummy);
388  html->appendChild(body, dummy);
389  body->appendChild(pre, dummy);
390 }
391 
392 void HTMLTextTokenizer::write(const TokenizerString &str, bool /*appendData*/)
393 {
394  // A potential worry here is the document being modified by
395  // a script while we're still loading. To handle that, we always look up
396  // the pre again, and append to it, even for document.write mess
397  // and the like.
398  RefPtr<NodeListImpl> coll = m_doc->getElementsByTagName("pre");
399  if (coll->length() >= 1ul) {
400  int dummy;
401  coll->item(0)->appendChild(m_doc->createTextNode(str.toString()), dummy);
402  }
403 }
404 
405 HTMLTextDocumentImpl::HTMLTextDocumentImpl(KHTMLView *v): HTMLDocumentImpl(v)
406 {}
407 
408 khtml::Tokenizer *HTMLTextDocumentImpl::createTokenizer()
409 {
410  return new HTMLTextTokenizer(this);
411 }
412 
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
Node appendChild(const Node &newChild)
Adds the node newChild to the end of the list of children of this node.
Definition: dom_node.cpp:354
void write(const DOMString &text)
Write a string of text to a document stream opened by open() .
This file is part of the HTML rendering engine for KDE.
Renders and displays HTML in a QScrollArea.
Definition: khtmlview.h:97
bool isValid() const const
QDBusConnection sessionBus()
QMap::const_iterator constFind(const Key &key) const const
const QList< QKeySequence > & begin()
KHTMLView * view() const
Definition: dom_doc.cpp:524
Node replaceChild(const Node &newChild, const Node &oldChild)
Replaces the child node oldChild with newChild in the list of children, and returns the oldChild node...
Definition: dom_node.cpp:327
DOMString title() const
The title of a document as specified by the TITLE element in the head of the document.
QWidget * topLevelWidget() const const
void setTitle(const DOMString &)
see title
QDBusReply::Type value() const const
const char * constData() const const
This class implements the basic string we use in the DOM.
Definition: dom_string.h:44
WId winId() const const
This library provides a full-featured HTML parser and widget.
const QList< QKeySequence > & end()
QByteArray toLatin1() const const
Element documentElement() const
This is a convenience attribute that allows direct access to the child node that is the root element ...
Definition: dom_doc.cpp:243
void updateRendering()
not part of the DOM
Definition: dom_doc.cpp:703
NodeList which lists all Nodes in a Element with a given "name=" tag.
DOMString URL() const
The absolute URI of the document.
HTMLElement body() const
The element that contains the content for the document.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:01 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.