KHtml

html_objectimpl.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) 2000 Stefan Schimanski ([email protected])
7  * (C) 2007, 2008 Maks Orlovich ([email protected])
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB. If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24 #include "html/html_objectimpl.h"
25 
26 #include "khtml_part.h"
27 #include "dom/dom_string.h"
28 #include "imload/imagemanager.h"
29 #include "khtmlview.h"
30 #include <QCharRef>
31 #include <QVariant>
32 #include <QMap>
33 #include <QTimer>
34 #include <QImageReader>
35 
36 #include "khtml_debug.h"
37 #include <kmessagebox.h>
38 #include <qmimedatabase.h>
39 
40 #include "xml/dom_docimpl.h"
41 #include "css/cssstyleselector.h"
42 #include "css/cssproperties.h"
43 #include "css/cssvalues.h"
44 #include "rendering/render_frames.h"
45 #include "rendering/render_image.h"
46 #include "xml/dom2_eventsimpl.h"
47 
48 using namespace DOM;
49 using namespace khtml;
50 
51 HTMLPartContainerElementImpl::HTMLPartContainerElementImpl(DocumentImpl *doc)
52  : HTMLElementImpl(doc)
53 {
54  m_needToComputeContent = true;
55  m_childWidget = nullptr;
56 }
57 
58 HTMLPartContainerElementImpl::~HTMLPartContainerElementImpl()
59 {
60  // Kill the renderer here, since we are asking for a widget to be deleted
61  if (m_render) {
62  detach();
63  }
64 
65  if (m_childWidget) {
66  m_childWidget->deleteLater();
67  }
68 }
69 
70 void HTMLPartContainerElementImpl::recalcStyle(StyleChange ch)
71 {
72  computeContentIfNeeded();
73 
74  HTMLElementImpl::recalcStyle(ch);
75 }
76 
77 void HTMLPartContainerElementImpl::close()
78 {
79  HTMLElementImpl::close(); // Do it first, to make sure closed() is set.
80  computeContentIfNeeded();
81 }
82 
83 void HTMLPartContainerElementImpl::computeContentIfNeeded()
84 {
85  if (!m_needToComputeContent) {
86  return;
87  }
88 
89  m_needToComputeContent = false;
90  computeContent();
91 }
92 
93 void HTMLPartContainerElementImpl::setNeedComputeContent()
94 {
95  m_needToComputeContent = true;
96  if (closed()) {
97  setChanged(); //React quickly when not in the middle of parsing..
98  }
99 }
100 
101 void HTMLPartContainerElementImpl::setWidget(QWidget *widget)
102 {
103  if (widget == m_childWidget) {
104  return; // The same part got navigated. Don't do anything
105  }
106 
107  QWidget *oldWidget = m_childWidget;
108  m_childWidget = widget;
109  if (m_childWidget) {
110  m_childWidget->hide();
111  }
112 
113  setWidgetNotify(m_childWidget);
114  if (oldWidget) {
115  oldWidget->hide();
116  oldWidget->deleteLater();
117  }
118 }
119 
120 void HTMLPartContainerElementImpl::partLoadingErrorNotify()
121 {
122  clearChildWidget();
123 }
124 
125 void HTMLPartContainerElementImpl::clearChildWidget()
126 {
127  setWidget(nullptr);
128 }
129 
130 bool HTMLPartContainerElementImpl::mimetypeHandledInternally(const QString &)
131 {
132  return false;
133 }
134 
135 void HTMLPartContainerElementImpl::slotEmitLoadEvent()
136 {
137  dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false);
138 }
139 
140 void HTMLPartContainerElementImpl::postResizeEvent()
141 {
142  QApplication::postEvent(this, new QEvent(static_cast<QEvent::Type>(DOMCFResizeEvent)));
143 }
144 
145 void HTMLPartContainerElementImpl::sendPostedResizeEvents()
146 {
147  QApplication::sendPostedEvents(nullptr, DOMCFResizeEvent);
148 }
149 
150 bool HTMLPartContainerElementImpl::event(QEvent *e)
151 {
152  if (e->type() == static_cast<QEvent::Type>(DOMCFResizeEvent)) {
153  dispatchWindowEvent(EventImpl::RESIZE_EVENT, false, false);
154  e->accept();
155  return true;
156  }
157  return QObject::event(e);
158 }
159 
160 // -------------------------------------------------------------------------
161 HTMLObjectBaseElementImpl::HTMLObjectBaseElementImpl(DocumentImpl *doc)
162  : HTMLPartContainerElementImpl(doc)
163 {
164  m_renderAlternative = false;
165  m_imageLike = false;
166  m_rerender = false;
167 }
168 
169 void HTMLObjectBaseElementImpl::setServiceType(const QString &val)
170 {
171  serviceType = val.toLower();
172  int pos = serviceType.indexOf(";");
173  if (pos != -1) {
174  serviceType.truncate(pos);
175  }
176 }
177 
178 void HTMLObjectBaseElementImpl::parseAttribute(AttributeImpl *attr)
179 {
180  switch (attr->id()) {
181  case ATTR_TYPE:
182  case ATTR_CODETYPE:
183  if (attr->val()) {
184  setServiceType(attr->val()->string());
185  setNeedComputeContent();
186  }
187  break;
188  case ATTR_WIDTH:
189  if (!attr->value().isEmpty()) {
190  addCSSLength(CSS_PROP_WIDTH, attr->value());
191  } else {
192  removeCSSProperty(CSS_PROP_WIDTH);
193  }
194  break;
195  case ATTR_HEIGHT:
196  if (!attr->value().isEmpty()) {
197  addCSSLength(CSS_PROP_HEIGHT, attr->value());
198  } else {
199  removeCSSProperty(CSS_PROP_HEIGHT);
200  }
201  break;
202  case ATTR_NAME:
203  if (inDocument() && m_name != attr->value()) {
204  document()->underDocNamedCache().remove(m_name, this);
205  document()->underDocNamedCache().add(attr->value(), this);
206  }
207  m_name = attr->value();
208  //fallthrough
209  default:
210  HTMLElementImpl::parseAttribute(attr);
211  }
212 }
213 
214 void HTMLObjectBaseElementImpl::defaultEventHandler(EventImpl *e)
215 {
216  // ### duplicated in HTMLIFrameElementImpl
217  if (e->target() == this && m_render && m_render->isWidget()
218  && static_cast<RenderWidget *>(m_render)->isRedirectedWidget()
219  && qobject_cast<KHTMLView *>(static_cast<RenderWidget *>(m_render)->widget())) {
220  switch (e->id()) {
221  case EventImpl::MOUSEDOWN_EVENT:
222  case EventImpl::MOUSEUP_EVENT:
223  case EventImpl::MOUSEMOVE_EVENT:
224  case EventImpl::MOUSEOUT_EVENT:
225  case EventImpl::MOUSEOVER_EVENT:
226  case EventImpl::KHTML_MOUSEWHEEL_EVENT:
227  case EventImpl::KEYDOWN_EVENT:
228  case EventImpl::KEYUP_EVENT:
229  case EventImpl::KEYPRESS_EVENT:
230  case EventImpl::DOMFOCUSIN_EVENT:
231  case EventImpl::DOMFOCUSOUT_EVENT:
232  if (static_cast<RenderWidget *>(m_render)->handleEvent(*e)) {
233  e->setDefaultHandled();
234  }
235  default:
236  break;
237  }
238  }
239  HTMLElementImpl::defaultEventHandler(e);
240 }
241 
242 void HTMLObjectBaseElementImpl::removedFromDocument()
243 {
244  document()->underDocNamedCache().remove(m_name, this);
245 
246  // When removed from document, we destroy the widget/plugin.
247  // We have to do it here and not just call setNeedComputeContent(),
248  // since khtml will not try to restyle changed() things not in document.
249  clearChildWidget();
250 
251  HTMLPartContainerElementImpl::removedFromDocument();
252 }
253 
254 void HTMLObjectBaseElementImpl::insertedIntoDocument()
255 {
256  document()->underDocNamedCache().add(m_name, this);
257  setNeedComputeContent();
258  HTMLPartContainerElementImpl::insertedIntoDocument();
259 }
260 
261 void HTMLObjectBaseElementImpl::removeId(const DOMString &id)
262 {
263  document()->underDocNamedCache().remove(id, this);
264  HTMLElementImpl::removeId(id);
265 }
266 
267 void HTMLObjectBaseElementImpl::addId(const DOMString &id)
268 {
269  document()->underDocNamedCache().add(id, this);
270  HTMLElementImpl::addId(id);
271 }
272 
273 void HTMLObjectBaseElementImpl::requestRerender()
274 {
275  if (m_rerender) {
276  return;
277  }
278  m_rerender = true;
279  QTimer::singleShot(0, this, SLOT(slotRerender()));
280 }
281 
282 void HTMLObjectBaseElementImpl::slotRerender()
283 {
284  // the singleshot timer might have fired after we're removed
285  // from the document, but not yet deleted due to references
286  if (!inDocument() || !m_rerender) {
287  return;
288  }
289 
290  // ### there can be a m_render if this is called from our attach indirectly
291  if (attached() || m_render) {
292  detach();
293  attach();
294  }
295 
296  m_rerender = false;
297 }
298 
299 void HTMLObjectBaseElementImpl::attach()
300 {
301  assert(!attached());
302  assert(!m_render);
303 
304  computeContentIfNeeded();
305  m_rerender = false;
306 
307  if (m_renderAlternative && !m_imageLike) {
308  // render alternative content
309  ElementImpl::attach();
310  return;
311  }
312 
313  if (!parentNode()->renderer()) {
314  NodeBaseImpl::attach();
315  return;
316  }
317 
318  RenderStyle *_style = document()->styleSelector()->styleForElement(this);
319  _style->ref();
320 
321  if (parentNode()->renderer() && parentNode()->renderer()->childAllowed() &&
322  _style->display() != NONE) {
323  if (m_imageLike) {
324  m_render = new(document()->renderArena()) RenderImage(this);
325  } else {
326  m_render = new(document()->renderArena()) RenderPartObject(this);
327  // If we already have a widget, set it.
328  if (childWidget()) {
329  static_cast<RenderFrame *>(m_render)->setWidget(childWidget());
330  }
331  }
332 
333  m_render->setStyle(_style);
334  parentNode()->renderer()->addChild(m_render, nextRenderer());
335  if (m_imageLike) {
336  m_render->updateFromElement();
337  }
338  }
339 
340  _style->deref();
341  NodeBaseImpl::attach();
342 }
343 
344 HTMLEmbedElementImpl *HTMLObjectBaseElementImpl::relevantEmbed()
345 {
346  for (NodeImpl *child = firstChild(); child; child = child->nextSibling()) {
347  if (child->id() == ID_EMBED) {
348  return static_cast<HTMLEmbedElementImpl *>(child);
349  }
350  }
351 
352  return nullptr;
353 }
354 
355 bool HTMLObjectBaseElementImpl::mimetypeHandledInternally(const QString &mime)
356 {
357  QStringList supportedImageTypes = khtmlImLoad::ImageManager::loaderDatabase()->supportedMimeTypes();
358 
359  bool newImageLike = supportedImageTypes.contains(mime);
360 
361  if (newImageLike != m_imageLike) {
362  m_imageLike = newImageLike;
363  requestRerender();
364  }
365 
366  return newImageLike; // No need for kpart for that.
367 }
368 
369 void HTMLObjectBaseElementImpl::computeContent()
370 {
371  QStringList params;
372  QString effectiveURL = url; // May be overwritten by some of the <params>
373  // if the URL isn't there
374  QString effectiveServiceType = serviceType;
375 
376  // We need to wait until everything has parsed, since we need the <param>s,
377  // and the embedded <embed>
378  if (!closed()) {
379  setNeedComputeContent();
380  return;
381  }
382 
383  // Not in document => no plugin.
384  if (!inDocument()) {
385  clearChildWidget();
386  return;
387  }
388 
389  // Collect information from <param> children for ...
390  // It also sometimes supplements or replaces some of the element's attributes
391  for (NodeImpl *child = firstChild(); child; child = child->nextSibling()) {
392  if (child->id() == ID_PARAM) {
393  HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>(child);
394 
395  QString aStr = p->name();
396  aStr += QLatin1String("=\"");
397  aStr += p->value();
398  aStr += QLatin1String("\"");
399  QString name_lower = p->name().toLower();
400  if (name_lower == QLatin1String("type") && id() != ID_APPLET) {
401  setServiceType(p->value());
402  effectiveServiceType = serviceType;
403  } else if (effectiveURL.isEmpty() &&
404  (name_lower == QLatin1String("src") ||
405  name_lower == QLatin1String("movie") ||
406  name_lower == QLatin1String("code"))) {
407  effectiveURL = p->value();
408  }
409  params.append(aStr);
410  }
411  }
412 
413  // For <applet>(?) and <embed> we also make each attribute a part parameter
414  if (id() != ID_OBJECT) {
415  NamedAttrMapImpl *a = attributes();
416  if (a) {
417  for (unsigned i = 0; i < a->length(); ++i) {
418  NodeImpl::Id id = a->idAt(i);
419  DOMString value = a->valueAt(i);
420  params.append(LocalName::fromId(localNamePart(id)).toString().string() + "=\"" + value.string() + "\"");
421  }
422  }
423  }
424 
425  params.append(QLatin1String("__KHTML__PLUGINEMBED=\"YES\""));
426  params.append(QString::fromLatin1("__KHTML__PLUGINBASEURL=\"%1\"").arg(document()->baseURL().url()));
427  params.append(QString::fromLatin1("__KHTML__PLUGINPAGEURL=\"%1\"").arg(document()->URL().url()));
428 
429  // Non-embed elements parse a bunch of attributes and inherit things off <embed>, if any
430  HTMLEmbedElementImpl *embed = relevantEmbed();
431  if (id() != ID_EMBED) {
432  params.append(QString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg(classId));
433  params.append(QString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg(getAttribute(ATTR_CODEBASE).string()));
434 
435  if (embed && !embed->getAttribute(ATTR_WIDTH).isEmpty()) {
436  setAttribute(ATTR_WIDTH, embed->getAttribute(ATTR_WIDTH));
437  }
438 
439  if (embed && !embed->getAttribute(ATTR_HEIGHT).isEmpty()) {
440  setAttribute(ATTR_HEIGHT, embed->getAttribute(ATTR_HEIGHT));
441  }
442 
443  if (!getAttribute(ATTR_WIDTH).isEmpty()) {
444  params.append(QString::fromLatin1("WIDTH=\"%1\"").arg(getAttribute(ATTR_WIDTH).string()));
445  }
446 
447  if (!getAttribute(ATTR_HEIGHT).isEmpty()) {
448  params.append(QString::fromLatin1("HEIGHT=\"%1\"").arg(getAttribute(ATTR_HEIGHT).string()));
449  }
450 
451  // Fix up the serviceType from embed, or applet info..
452  if (embed) {
453  effectiveURL = embed->url;
454  if (!embed->serviceType.isEmpty()) {
455  effectiveServiceType = embed->serviceType;
456  }
457  } else if (effectiveURL.isEmpty() &&
458  classId.startsWith(QLatin1String("java:"))) {
459  effectiveServiceType = "application/x-java-applet";
460  effectiveURL = classId.mid(5);
461  }
462 
463  // Translate ActiveX gibberish into mimetypes
464  if ((effectiveServiceType.isEmpty() || serviceType == "application/x-oleobject") && !classId.isEmpty()) {
465  if (classId.indexOf(QString::fromLatin1("D27CDB6E-AE6D-11cf-96B8-444553540000")) >= 0) {
466  effectiveServiceType = "application/x-shockwave-flash";
467  } else if (classId.indexOf(QLatin1String("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) >= 0) {
468  effectiveServiceType = "audio/x-pn-realaudio-plugin";
469  } else if (classId.indexOf(QLatin1String("8AD9C840-044E-11D1-B3E9-00805F499D93")) >= 0 ||
470  classId.indexOf(QLatin1String("CAFEEFAC-0014-0000-0000-ABCDEFFEDCBA")) >= 0) {
471  effectiveServiceType = "application/x-java-applet";
472  }
473  // http://www.apple.com/quicktime/tools_tips/tutorials/activex.html
474  else if (classId.indexOf(QLatin1String("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) >= 0) {
475  effectiveServiceType = "video/quicktime";
476  }
477  // http://msdn.microsoft.com/library/en-us/dnwmt/html/adding_windows_media_to_web_pages__etse.asp?frame=true
478  else if (classId.indexOf(QString::fromLatin1("6BF52A52-394A-11d3-B153-00C04F79FAA6")) >= 0 ||
479  classId.indexOf(QString::fromLatin1("22D6f312-B0F6-11D0-94AB-0080C74C7E95")) >= 0) {
480  effectiveServiceType = "video/x-msvideo";
481  } else {
482  // qCDebug(KHTML_LOG) << "ActiveX classId " << classId;
483  }
484  // TODO: add more plugins here
485  }
486  }
487 
488  if (effectiveServiceType.isEmpty() &&
489  effectiveURL.startsWith(QLatin1String("data:"))) {
490  // Extract the MIME type from the data URL.
491  int index = effectiveURL.indexOf(';');
492  if (index == -1) {
493  index = effectiveURL.indexOf(',');
494  }
495  if (index != -1) {
496  int len = index - 5;
497  if (len > 0) {
498  effectiveServiceType = effectiveURL.mid(5, len);
499  } else {
500  effectiveServiceType = "text/plain"; // Data URLs with no MIME type are considered text/plain.
501  }
502  }
503  }
504 
505  // Figure out if may be we're image-like. In this case, we don't need to load anything,
506  // but may need to do a detach/attach
507  QStringList supportedImageTypes = khtmlImLoad::ImageManager::loaderDatabase()->supportedMimeTypes();
508 
509  bool newImageLike = effectiveServiceType.startsWith(QLatin1String("image/")) && supportedImageTypes.contains(effectiveServiceType);
510 
511  if (newImageLike != m_imageLike) {
512  m_imageLike = newImageLike;
513  requestRerender();
514  }
515 
516  if (m_imageLike) {
517  return;
518  }
519 
520  // Now see if we have to render alternate content.
521  bool newRenderAlternative = false;
522 
523  // If we aren't permitted to load this by security policy, render alternative content instead.
524  if (!document()->isURLAllowed(effectiveURL)) {
525  newRenderAlternative = true;
526  }
527 
528  // If Java is off, render alternative as well...
529  if (effectiveServiceType == "application/x-java-applet") {
530  KHTMLPart *p = document()->part();
531  if (!p || !p->javaEnabled()) {
532  newRenderAlternative = true;
533  }
534  }
535 
536  // If there is no <embed> (here or as a child), and we don't have a type + url to go on,
537  // we need to render alternative as well
538  if (!embed && effectiveURL.isEmpty() && effectiveServiceType.isEmpty()) {
539  newRenderAlternative = true;
540  }
541 
542  if (newRenderAlternative != m_renderAlternative) {
543  m_renderAlternative = newRenderAlternative;
544  requestRerender();
545  }
546 
547  if (m_renderAlternative) {
548  return;
549  }
550 
551  KHTMLPart *part = document()->part();
552  clearChildWidget();
553 
554  // qCDebug(KHTML_LOG) << effectiveURL << effectiveServiceType << params;
555 
556  if (!part->loadObjectElement(this, effectiveURL, effectiveServiceType, params)) {
557  // Looks like we are gonna need alternative content after all...
558  m_renderAlternative = true;
559  }
560 
561  // Either way, we need to re-attach, either for alternative content, or because
562  // we got the part..
563  requestRerender();
564 }
565 
566 void HTMLObjectBaseElementImpl::setWidgetNotify(QWidget *widget)
567 {
568  // Ick.
569  if (m_render && strcmp(m_render->renderName(), "RenderPartObject") == 0) {
570  static_cast<RenderPartObject *>(m_render)->setWidget(widget);
571  }
572 }
573 
574 void HTMLObjectBaseElementImpl::renderAlternative()
575 {
576  if (m_renderAlternative) {
577  return;
578  }
579 
580  m_renderAlternative = true;
581  requestRerender();
582 }
583 
584 void HTMLObjectBaseElementImpl::partLoadingErrorNotify()
585 {
586  // Defer ourselves from the current event loop (to prevent crashes due to the message box staying up)
587  QTimer::singleShot(0, this, SLOT(slotPartLoadingErrorNotify()));
588 
589  // Either way, we don't have stuff to display, so have to render alternative content.
590  if (!m_renderAlternative) {
591  m_renderAlternative = true;
592  requestRerender();
593  }
594 
595  clearChildWidget();
596 }
597 
598 void HTMLObjectBaseElementImpl::slotPartLoadingErrorNotify()
599 {
600  // If we have an embed, we may be able to tell the user where to
601  // download the plugin.
602 
603  HTMLEmbedElementImpl *embed = relevantEmbed();
604  QString serviceType; // shadows ours, but we don't care.
605 
606  if (!embed) {
607  return;
608  }
609 
610  serviceType = embed->serviceType;
611 
612  KHTMLPart *part = document()->part();
614 
615  if (!embed->pluginPage.isEmpty() && ext) {
616  // Prepare the mimetype to show in the question (comment if available, name as fallback)
617  QString mimeName = serviceType;
618  QMimeDatabase db;
619  QMimeType mime = db.mimeTypeForName(serviceType);
620  if (mime.isValid()) {
621  mimeName = mime.comment();
622  }
623 
624  // Check if we already asked the user, for this page
625  if (!mimeName.isEmpty() && !part->pluginPageQuestionAsked(serviceType)) {
626  part->setPluginPageQuestionAsked(serviceType);
627 
628  // Prepare the URL to show in the question (host only if http, to make it short)
629  QUrl pluginPageURL(embed->pluginPage);
630  QString shortURL = pluginPageURL.scheme() == "http" ? pluginPageURL.host() : pluginPageURL.toDisplayString();
631  int res = KMessageBox::questionYesNo(part->view(),
632  i18n("No plugin found for '%1'.\nDo you want to download one from %2?", mimeName, shortURL),
633  i18n("Missing Plugin"), KGuiItem(i18n("Download")), KGuiItem(i18n("Do Not Download")), QString("plugin-") + serviceType);
634  if (res == KMessageBox::Yes) {
635  // Display vendor download page
636  ext->createNewWindow(pluginPageURL);
637  return;
638  }
639  }
640  }
641 }
642 
643 // -------------------------------------------------------------------------
644 
645 HTMLAppletElementImpl::HTMLAppletElementImpl(DocumentImpl *doc)
646  : HTMLObjectBaseElementImpl(doc)
647 {
648  serviceType = "application/x-java-applet";
649 }
650 
651 HTMLAppletElementImpl::~HTMLAppletElementImpl()
652 {
653 }
654 
655 NodeImpl::Id HTMLAppletElementImpl::id() const
656 {
657  return ID_APPLET;
658 }
659 
660 void HTMLAppletElementImpl::parseAttribute(AttributeImpl *attr)
661 {
662  switch (attr->id()) {
663  case ATTR_CODEBASE:
664  case ATTR_ARCHIVE:
665  case ATTR_CODE:
666  case ATTR_OBJECT:
667  case ATTR_ALT:
668  break;
669  case ATTR_ALIGN:
670  addHTMLAlignment(attr->value());
671  break;
672  case ATTR_VSPACE:
673  addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
674  addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
675  break;
676  case ATTR_HSPACE:
677  addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
678  addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
679  break;
680  case ATTR_VALIGN:
681  addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower());
682  break;
683  default:
684  HTMLObjectBaseElementImpl::parseAttribute(attr);
685  }
686 }
687 
688 void HTMLAppletElementImpl::computeContent()
689 {
690  DOMString codeBase = getAttribute(ATTR_CODEBASE);
691  DOMString code = getAttribute(ATTR_CODE);
692  if (!codeBase.isEmpty()) {
693  url = codeBase.string();
694  }
695  if (!code.isEmpty()) {
696  url = code.string();
697  }
698  HTMLObjectBaseElementImpl::computeContent();
699 }
700 
701 // -------------------------------------------------------------------------
702 
703 HTMLEmbedElementImpl::HTMLEmbedElementImpl(DocumentImpl *doc)
704  : HTMLObjectBaseElementImpl(doc)
705 {
706 }
707 
708 HTMLEmbedElementImpl::~HTMLEmbedElementImpl()
709 {
710 }
711 
712 NodeImpl::Id HTMLEmbedElementImpl::id() const
713 {
714  return ID_EMBED;
715 }
716 
717 HTMLEmbedElementImpl *HTMLEmbedElementImpl::relevantEmbed()
718 {
719  return this;
720 }
721 
722 void HTMLEmbedElementImpl::parseAttribute(AttributeImpl *attr)
723 {
724  switch (attr->id()) {
725  case ATTR_CODE:
726  case ATTR_SRC:
727  url = attr->value().trimSpaces().string();
728  setNeedComputeContent();
729  break;
730  case ATTR_BORDER:
731  addCSSLength(CSS_PROP_BORDER_WIDTH, attr->value());
732  addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
733  addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
734  addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
735  addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
736  break;
737  case ATTR_VSPACE:
738  addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
739  addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
740  break;
741  case ATTR_HSPACE:
742  addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
743  addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
744  break;
745  case ATTR_ALIGN:
746  addHTMLAlignment(attr->value());
747  break;
748  case ATTR_VALIGN:
749  addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower());
750  break;
751  case ATTR_PLUGINPAGE:
752  case ATTR_PLUGINSPAGE: {
753  pluginPage = attr->value().string();
754  break;
755  }
756  case ATTR_HIDDEN:
757  if (strcasecmp(attr->value(), "yes") == 0 || strcasecmp(attr->value(), "true") == 0) {
758  hidden = true;
759  } else {
760  hidden = false;
761  }
762  break;
763  default:
764  HTMLObjectBaseElementImpl::parseAttribute(attr);
765  }
766 }
767 
768 void HTMLEmbedElementImpl::attach()
769 {
770  if (parentNode()->id() == ID_OBJECT) {
771  NodeBaseImpl::attach();
772  } else {
773  HTMLObjectBaseElementImpl::attach();
774  }
775 }
776 
777 void HTMLEmbedElementImpl::computeContent()
778 {
779  if (parentNode()->id() != ID_OBJECT) {
780  HTMLObjectBaseElementImpl::computeContent();
781  }
782 }
783 
784 // -------------------------------------------------------------------------
785 
786 HTMLObjectElementImpl::HTMLObjectElementImpl(DocumentImpl *doc)
787  : HTMLObjectBaseElementImpl(doc)
788 {
789 }
790 
791 HTMLObjectElementImpl::~HTMLObjectElementImpl()
792 {
793 }
794 
795 NodeImpl::Id HTMLObjectElementImpl::id() const
796 {
797  return ID_OBJECT;
798 }
799 
800 HTMLFormElementImpl *HTMLObjectElementImpl::form() const
801 {
802  return nullptr;
803 }
804 
805 void HTMLObjectElementImpl::parseAttribute(AttributeImpl *attr)
806 {
807  switch (attr->id()) {
808  case ATTR_DATA:
809  url = attr->value().trimSpaces().string();
810  setNeedComputeContent();
811  break;
812  case ATTR_CLASSID:
813  classId = attr->value().string();
814  setNeedComputeContent();
815  break;
816  case ATTR_ONLOAD: // ### support load/unload on object elements
817  setHTMLEventListener(EventImpl::LOAD_EVENT,
818  document()->createHTMLEventListener(attr->value().string(), "onload", this));
819  break;
820  case ATTR_ONUNLOAD:
821  setHTMLEventListener(EventImpl::UNLOAD_EVENT,
822  document()->createHTMLEventListener(attr->value().string(), "onunload", this));
823  break;
824  case ATTR_VSPACE:
825  addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
826  addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
827  break;
828  case ATTR_HSPACE:
829  addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
830  addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
831  break;
832  case ATTR_ALIGN:
833  addHTMLAlignment(attr->value());
834  break;
835  case ATTR_VALIGN:
836  addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower());
837  break;
838  default:
839  HTMLObjectBaseElementImpl::parseAttribute(attr);
840  }
841 }
842 
843 DocumentImpl *HTMLObjectElementImpl::contentDocument() const
844 {
845  QWidget *widget = childWidget();
846  if (widget && qobject_cast<KHTMLView *>(widget)) {
847  return static_cast<KHTMLView *>(widget)->part()->xmlDocImpl();
848  }
849  return nullptr;
850 }
851 
852 void HTMLObjectElementImpl::attach()
853 {
854  HTMLObjectBaseElementImpl::attach();
855 }
856 
857 // -------------------------------------------------------------------------
858 
859 NodeImpl::Id HTMLParamElementImpl::id() const
860 {
861  return ID_PARAM;
862 }
863 
864 void HTMLParamElementImpl::parseAttribute(AttributeImpl *attr)
865 {
866  switch (attr->id()) {
867  case ATTR_VALUE:
868  m_value = attr->value().string();
869  break;
870  case ATTR_ID:
871  if (document()->htmlMode() != DocumentImpl::XHtml) {
872  break;
873  }
874  // fall through
875  case ATTR_NAME:
876  m_name = attr->value().string();
877  // fall through
878  default:
879  HTMLElementImpl::parseAttribute(attr);
880  }
881 }
882 
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QEvent::Type type() const const
This file is part of the HTML rendering engine for KDE.
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
This class is khtml&#39;s main class.
Definition: khtml_part.h:208
DOMString value() const
The value of a run-time parameter.
Renders and displays HTML in a QScrollArea.
Definition: khtmlview.h:97
NamedNodeMap attributes() const
A NamedNodeMap containing the attributes of this node (if it is an Element ) or null otherwise...
Definition: dom_node.cpp:298
unsigned long index() const
Definition: dom_node.cpp:517
virtual bool event(QEvent *e)
KHTMLView * view() const
Returns a pointer to the HTML document&#39;s view.
void setAttribute(const DOMString &name, const DOMString &value)
Adds a new attribute.
void append(const T &value)
Node parentNode() const
The parent of this node.
Definition: dom_node.cpp:250
KParts::BrowserExtension * browserExtension() const
Returns a pointer to the KParts::BrowserExtension.
bool isEmpty() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
This class implements the basic string we use in the DOM.
Definition: dom_string.h:44
void deleteLater()
void sendPostedEvents(QObject *receiver, int event_type)
void hide()
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
ButtonCode questionYesNo(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const QString &dontAskAgainName=QString(), Options options=Notify)
QString toLower() const const
void accept()
Node firstChild() const
The first child of this node.
Definition: dom_node.cpp:266
bool isValid() const const
QString i18n(const char *text, const TYPE &arg...)
This library provides a full-featured HTML parser and widget.
QString mid(int position, int n) const const
char * toString(const T &value)
DOMString getAttribute(const DOMString &name)
Retrieves an attribute value by name.
void createNewWindow(const QUrl &url, const KParts::OpenUrlArguments &arguments=KParts::OpenUrlArguments(), const KParts::BrowserArguments &browserArguments=KParts::BrowserArguments(), const KParts::WindowArgs &windowArgs=KParts::WindowArgs(), KParts::ReadOnlyPart **part=nullptr)
QString fromLatin1(const char *str, int size)
void postEvent(QObject *receiver, QEvent *event, int priority)
Node nextSibling() const
The node immediately following this node.
Definition: dom_node.cpp:290
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Oct 25 2021 22:48:15 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.