File indexing completed on 2024-05-05 16:10:14
0001 /** 0002 * This file is part of the DOM implementation for KDE. 0003 * 0004 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 0005 * (C) 1999 Antti Koivisto (koivisto@kde.org) 0006 * (C) 2000 Stefan Schimanski (1Stein@gmx.de) 0007 * (C) 2007, 2008 Maks Orlovich (maksim@kde.org) 0008 * 0009 * This library is free software; you can redistribute it and/or 0010 * modify it under the terms of the GNU Library General Public 0011 * License as published by the Free Software Foundation; either 0012 * version 2 of the License, or (at your option) any later version. 0013 * 0014 * This library is distributed in the hope that it will be useful, 0015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0017 * Library General Public License for more details. 0018 * 0019 * You should have received a copy of the GNU Library General Public License 0020 * along with this library; see the file COPYING.LIB. If not, write to 0021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0022 * Boston, MA 02110-1301, USA. 0023 */ 0024 #include "html/html_objectimpl.h" 0025 0026 #include "khtml_part.h" 0027 #include "dom/dom_string.h" 0028 #include "imload/imagemanager.h" 0029 #include "khtmlview.h" 0030 #include <QCharRef> 0031 #include <QVariant> 0032 #include <QMap> 0033 #include <QTimer> 0034 #include <QImageReader> 0035 0036 #include "khtml_debug.h" 0037 #include <kmessagebox.h> 0038 #include <qmimedatabase.h> 0039 0040 #include "xml/dom_docimpl.h" 0041 #include "css/cssstyleselector.h" 0042 #include "css/cssproperties.h" 0043 #include "css/cssvalues.h" 0044 #include "rendering/render_frames.h" 0045 #include "rendering/render_image.h" 0046 #include "xml/dom2_eventsimpl.h" 0047 0048 using namespace DOM; 0049 using namespace khtml; 0050 0051 HTMLPartContainerElementImpl::HTMLPartContainerElementImpl(DocumentImpl *doc) 0052 : HTMLElementImpl(doc) 0053 { 0054 m_needToComputeContent = true; 0055 m_childWidget = nullptr; 0056 } 0057 0058 HTMLPartContainerElementImpl::~HTMLPartContainerElementImpl() 0059 { 0060 // Kill the renderer here, since we are asking for a widget to be deleted 0061 if (m_render) { 0062 detach(); 0063 } 0064 0065 if (m_childWidget) { 0066 m_childWidget->deleteLater(); 0067 } 0068 } 0069 0070 void HTMLPartContainerElementImpl::recalcStyle(StyleChange ch) 0071 { 0072 computeContentIfNeeded(); 0073 0074 HTMLElementImpl::recalcStyle(ch); 0075 } 0076 0077 void HTMLPartContainerElementImpl::close() 0078 { 0079 HTMLElementImpl::close(); // Do it first, to make sure closed() is set. 0080 computeContentIfNeeded(); 0081 } 0082 0083 void HTMLPartContainerElementImpl::computeContentIfNeeded() 0084 { 0085 if (!m_needToComputeContent) { 0086 return; 0087 } 0088 0089 m_needToComputeContent = false; 0090 computeContent(); 0091 } 0092 0093 void HTMLPartContainerElementImpl::setNeedComputeContent() 0094 { 0095 m_needToComputeContent = true; 0096 if (closed()) { 0097 setChanged(); //React quickly when not in the middle of parsing.. 0098 } 0099 } 0100 0101 void HTMLPartContainerElementImpl::setWidget(QWidget *widget) 0102 { 0103 if (widget == m_childWidget) { 0104 return; // The same part got navigated. Don't do anything 0105 } 0106 0107 QWidget *oldWidget = m_childWidget; 0108 m_childWidget = widget; 0109 if (m_childWidget) { 0110 m_childWidget->hide(); 0111 } 0112 0113 setWidgetNotify(m_childWidget); 0114 if (oldWidget) { 0115 oldWidget->hide(); 0116 oldWidget->deleteLater(); 0117 } 0118 } 0119 0120 void HTMLPartContainerElementImpl::partLoadingErrorNotify() 0121 { 0122 clearChildWidget(); 0123 } 0124 0125 void HTMLPartContainerElementImpl::clearChildWidget() 0126 { 0127 setWidget(nullptr); 0128 } 0129 0130 bool HTMLPartContainerElementImpl::mimetypeHandledInternally(const QString &) 0131 { 0132 return false; 0133 } 0134 0135 void HTMLPartContainerElementImpl::slotEmitLoadEvent() 0136 { 0137 dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false); 0138 } 0139 0140 void HTMLPartContainerElementImpl::postResizeEvent() 0141 { 0142 QApplication::postEvent(this, new QEvent(static_cast<QEvent::Type>(DOMCFResizeEvent))); 0143 } 0144 0145 void HTMLPartContainerElementImpl::sendPostedResizeEvents() 0146 { 0147 QApplication::sendPostedEvents(nullptr, DOMCFResizeEvent); 0148 } 0149 0150 bool HTMLPartContainerElementImpl::event(QEvent *e) 0151 { 0152 if (e->type() == static_cast<QEvent::Type>(DOMCFResizeEvent)) { 0153 dispatchWindowEvent(EventImpl::RESIZE_EVENT, false, false); 0154 e->accept(); 0155 return true; 0156 } 0157 return QObject::event(e); 0158 } 0159 0160 // ------------------------------------------------------------------------- 0161 HTMLObjectBaseElementImpl::HTMLObjectBaseElementImpl(DocumentImpl *doc) 0162 : HTMLPartContainerElementImpl(doc) 0163 { 0164 m_renderAlternative = false; 0165 m_imageLike = false; 0166 m_rerender = false; 0167 } 0168 0169 void HTMLObjectBaseElementImpl::setServiceType(const QString &val) 0170 { 0171 serviceType = val.toLower(); 0172 int pos = serviceType.indexOf(";"); 0173 if (pos != -1) { 0174 serviceType.truncate(pos); 0175 } 0176 } 0177 0178 void HTMLObjectBaseElementImpl::parseAttribute(AttributeImpl *attr) 0179 { 0180 switch (attr->id()) { 0181 case ATTR_TYPE: 0182 case ATTR_CODETYPE: 0183 if (attr->val()) { 0184 setServiceType(attr->val()->string()); 0185 setNeedComputeContent(); 0186 } 0187 break; 0188 case ATTR_WIDTH: 0189 if (!attr->value().isEmpty()) { 0190 addCSSLength(CSS_PROP_WIDTH, attr->value()); 0191 } else { 0192 removeCSSProperty(CSS_PROP_WIDTH); 0193 } 0194 break; 0195 case ATTR_HEIGHT: 0196 if (!attr->value().isEmpty()) { 0197 addCSSLength(CSS_PROP_HEIGHT, attr->value()); 0198 } else { 0199 removeCSSProperty(CSS_PROP_HEIGHT); 0200 } 0201 break; 0202 case ATTR_NAME: 0203 if (inDocument() && m_name != attr->value()) { 0204 document()->underDocNamedCache().remove(m_name, this); 0205 document()->underDocNamedCache().add(attr->value(), this); 0206 } 0207 m_name = attr->value(); 0208 //fallthrough 0209 default: 0210 HTMLElementImpl::parseAttribute(attr); 0211 } 0212 } 0213 0214 void HTMLObjectBaseElementImpl::defaultEventHandler(EventImpl *e) 0215 { 0216 // ### duplicated in HTMLIFrameElementImpl 0217 if (e->target() == this && m_render && m_render->isWidget() 0218 && static_cast<RenderWidget *>(m_render)->isRedirectedWidget() 0219 && qobject_cast<KHTMLView *>(static_cast<RenderWidget *>(m_render)->widget())) { 0220 switch (e->id()) { 0221 case EventImpl::MOUSEDOWN_EVENT: 0222 case EventImpl::MOUSEUP_EVENT: 0223 case EventImpl::MOUSEMOVE_EVENT: 0224 case EventImpl::MOUSEOUT_EVENT: 0225 case EventImpl::MOUSEOVER_EVENT: 0226 case EventImpl::KHTML_MOUSEWHEEL_EVENT: 0227 case EventImpl::KEYDOWN_EVENT: 0228 case EventImpl::KEYUP_EVENT: 0229 case EventImpl::KEYPRESS_EVENT: 0230 case EventImpl::DOMFOCUSIN_EVENT: 0231 case EventImpl::DOMFOCUSOUT_EVENT: 0232 if (static_cast<RenderWidget *>(m_render)->handleEvent(*e)) { 0233 e->setDefaultHandled(); 0234 } 0235 default: 0236 break; 0237 } 0238 } 0239 HTMLElementImpl::defaultEventHandler(e); 0240 } 0241 0242 void HTMLObjectBaseElementImpl::removedFromDocument() 0243 { 0244 document()->underDocNamedCache().remove(m_name, this); 0245 0246 // When removed from document, we destroy the widget/plugin. 0247 // We have to do it here and not just call setNeedComputeContent(), 0248 // since khtml will not try to restyle changed() things not in document. 0249 clearChildWidget(); 0250 0251 HTMLPartContainerElementImpl::removedFromDocument(); 0252 } 0253 0254 void HTMLObjectBaseElementImpl::insertedIntoDocument() 0255 { 0256 document()->underDocNamedCache().add(m_name, this); 0257 setNeedComputeContent(); 0258 HTMLPartContainerElementImpl::insertedIntoDocument(); 0259 } 0260 0261 void HTMLObjectBaseElementImpl::removeId(const DOMString &id) 0262 { 0263 document()->underDocNamedCache().remove(id, this); 0264 HTMLElementImpl::removeId(id); 0265 } 0266 0267 void HTMLObjectBaseElementImpl::addId(const DOMString &id) 0268 { 0269 document()->underDocNamedCache().add(id, this); 0270 HTMLElementImpl::addId(id); 0271 } 0272 0273 void HTMLObjectBaseElementImpl::requestRerender() 0274 { 0275 if (m_rerender) { 0276 return; 0277 } 0278 m_rerender = true; 0279 QTimer::singleShot(0, this, SLOT(slotRerender())); 0280 } 0281 0282 void HTMLObjectBaseElementImpl::slotRerender() 0283 { 0284 // the singleshot timer might have fired after we're removed 0285 // from the document, but not yet deleted due to references 0286 if (!inDocument() || !m_rerender) { 0287 return; 0288 } 0289 0290 // ### there can be a m_render if this is called from our attach indirectly 0291 if (attached() || m_render) { 0292 detach(); 0293 attach(); 0294 } 0295 0296 m_rerender = false; 0297 } 0298 0299 void HTMLObjectBaseElementImpl::attach() 0300 { 0301 assert(!attached()); 0302 assert(!m_render); 0303 0304 computeContentIfNeeded(); 0305 m_rerender = false; 0306 0307 if (m_renderAlternative && !m_imageLike) { 0308 // render alternative content 0309 ElementImpl::attach(); 0310 return; 0311 } 0312 0313 if (!parentNode()->renderer()) { 0314 NodeBaseImpl::attach(); 0315 return; 0316 } 0317 0318 RenderStyle *_style = document()->styleSelector()->styleForElement(this); 0319 _style->ref(); 0320 0321 if (parentNode()->renderer() && parentNode()->renderer()->childAllowed() && 0322 _style->display() != NONE) { 0323 if (m_imageLike) { 0324 m_render = new(document()->renderArena()) RenderImage(this); 0325 } else { 0326 m_render = new(document()->renderArena()) RenderPartObject(this); 0327 // If we already have a widget, set it. 0328 if (childWidget()) { 0329 static_cast<RenderFrame *>(m_render)->setWidget(childWidget()); 0330 } 0331 } 0332 0333 m_render->setStyle(_style); 0334 parentNode()->renderer()->addChild(m_render, nextRenderer()); 0335 if (m_imageLike) { 0336 m_render->updateFromElement(); 0337 } 0338 } 0339 0340 _style->deref(); 0341 NodeBaseImpl::attach(); 0342 } 0343 0344 HTMLEmbedElementImpl *HTMLObjectBaseElementImpl::relevantEmbed() 0345 { 0346 for (NodeImpl *child = firstChild(); child; child = child->nextSibling()) { 0347 if (child->id() == ID_EMBED) { 0348 return static_cast<HTMLEmbedElementImpl *>(child); 0349 } 0350 } 0351 0352 return nullptr; 0353 } 0354 0355 bool HTMLObjectBaseElementImpl::mimetypeHandledInternally(const QString &mime) 0356 { 0357 QStringList supportedImageTypes = khtmlImLoad::ImageManager::loaderDatabase()->supportedMimeTypes(); 0358 0359 bool newImageLike = supportedImageTypes.contains(mime); 0360 0361 if (newImageLike != m_imageLike) { 0362 m_imageLike = newImageLike; 0363 requestRerender(); 0364 } 0365 0366 return newImageLike; // No need for kpart for that. 0367 } 0368 0369 void HTMLObjectBaseElementImpl::computeContent() 0370 { 0371 QStringList params; 0372 QString effectiveURL = url; // May be overwritten by some of the <params> 0373 // if the URL isn't there 0374 QString effectiveServiceType = serviceType; 0375 0376 // We need to wait until everything has parsed, since we need the <param>s, 0377 // and the embedded <embed> 0378 if (!closed()) { 0379 setNeedComputeContent(); 0380 return; 0381 } 0382 0383 // Not in document => no plugin. 0384 if (!inDocument()) { 0385 clearChildWidget(); 0386 return; 0387 } 0388 0389 // Collect information from <param> children for ... 0390 // It also sometimes supplements or replaces some of the element's attributes 0391 for (NodeImpl *child = firstChild(); child; child = child->nextSibling()) { 0392 if (child->id() == ID_PARAM) { 0393 HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>(child); 0394 0395 QString aStr = p->name(); 0396 aStr += QLatin1String("=\""); 0397 aStr += p->value(); 0398 aStr += QLatin1String("\""); 0399 QString name_lower = p->name().toLower(); 0400 if (name_lower == QLatin1String("type") && id() != ID_APPLET) { 0401 setServiceType(p->value()); 0402 effectiveServiceType = serviceType; 0403 } else if (effectiveURL.isEmpty() && 0404 (name_lower == QLatin1String("src") || 0405 name_lower == QLatin1String("movie") || 0406 name_lower == QLatin1String("code"))) { 0407 effectiveURL = p->value(); 0408 } 0409 params.append(aStr); 0410 } 0411 } 0412 0413 // For <applet>(?) and <embed> we also make each attribute a part parameter 0414 if (id() != ID_OBJECT) { 0415 NamedAttrMapImpl *a = attributes(); 0416 if (a) { 0417 for (unsigned i = 0; i < a->length(); ++i) { 0418 NodeImpl::Id id = a->idAt(i); 0419 DOMString value = a->valueAt(i); 0420 params.append(LocalName::fromId(localNamePart(id)).toString().string() + "=\"" + value.string() + "\""); 0421 } 0422 } 0423 } 0424 0425 params.append(QLatin1String("__KHTML__PLUGINEMBED=\"YES\"")); 0426 params.append(QString::fromLatin1("__KHTML__PLUGINBASEURL=\"%1\"").arg(document()->baseURL().url())); 0427 params.append(QString::fromLatin1("__KHTML__PLUGINPAGEURL=\"%1\"").arg(document()->URL().url())); 0428 0429 // Non-embed elements parse a bunch of attributes and inherit things off <embed>, if any 0430 HTMLEmbedElementImpl *embed = relevantEmbed(); 0431 if (id() != ID_EMBED) { 0432 params.append(QString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg(classId)); 0433 params.append(QString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg(getAttribute(ATTR_CODEBASE).string())); 0434 0435 if (embed && !embed->getAttribute(ATTR_WIDTH).isEmpty()) { 0436 setAttribute(ATTR_WIDTH, embed->getAttribute(ATTR_WIDTH)); 0437 } 0438 0439 if (embed && !embed->getAttribute(ATTR_HEIGHT).isEmpty()) { 0440 setAttribute(ATTR_HEIGHT, embed->getAttribute(ATTR_HEIGHT)); 0441 } 0442 0443 if (!getAttribute(ATTR_WIDTH).isEmpty()) { 0444 params.append(QString::fromLatin1("WIDTH=\"%1\"").arg(getAttribute(ATTR_WIDTH).string())); 0445 } 0446 0447 if (!getAttribute(ATTR_HEIGHT).isEmpty()) { 0448 params.append(QString::fromLatin1("HEIGHT=\"%1\"").arg(getAttribute(ATTR_HEIGHT).string())); 0449 } 0450 0451 // Fix up the serviceType from embed, or applet info.. 0452 if (embed) { 0453 effectiveURL = embed->url; 0454 if (!embed->serviceType.isEmpty()) { 0455 effectiveServiceType = embed->serviceType; 0456 } 0457 } else if (effectiveURL.isEmpty() && 0458 classId.startsWith(QLatin1String("java:"))) { 0459 effectiveServiceType = "application/x-java-applet"; 0460 effectiveURL = classId.mid(5); 0461 } 0462 0463 // Translate ActiveX gibberish into mimetypes 0464 if ((effectiveServiceType.isEmpty() || serviceType == "application/x-oleobject") && !classId.isEmpty()) { 0465 if (classId.indexOf(QString::fromLatin1("D27CDB6E-AE6D-11cf-96B8-444553540000")) >= 0) { 0466 effectiveServiceType = "application/x-shockwave-flash"; 0467 } else if (classId.indexOf(QLatin1String("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) >= 0) { 0468 effectiveServiceType = "audio/x-pn-realaudio-plugin"; 0469 } else if (classId.indexOf(QLatin1String("8AD9C840-044E-11D1-B3E9-00805F499D93")) >= 0 || 0470 classId.indexOf(QLatin1String("CAFEEFAC-0014-0000-0000-ABCDEFFEDCBA")) >= 0) { 0471 effectiveServiceType = "application/x-java-applet"; 0472 } 0473 // http://www.apple.com/quicktime/tools_tips/tutorials/activex.html 0474 else if (classId.indexOf(QLatin1String("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) >= 0) { 0475 effectiveServiceType = "video/quicktime"; 0476 } 0477 // http://msdn.microsoft.com/library/en-us/dnwmt/html/adding_windows_media_to_web_pages__etse.asp?frame=true 0478 else if (classId.indexOf(QString::fromLatin1("6BF52A52-394A-11d3-B153-00C04F79FAA6")) >= 0 || 0479 classId.indexOf(QString::fromLatin1("22D6f312-B0F6-11D0-94AB-0080C74C7E95")) >= 0) { 0480 effectiveServiceType = "video/x-msvideo"; 0481 } else { 0482 // qCDebug(KHTML_LOG) << "ActiveX classId " << classId; 0483 } 0484 // TODO: add more plugins here 0485 } 0486 } 0487 0488 if (effectiveServiceType.isEmpty() && 0489 effectiveURL.startsWith(QLatin1String("data:"))) { 0490 // Extract the MIME type from the data URL. 0491 int index = effectiveURL.indexOf(';'); 0492 if (index == -1) { 0493 index = effectiveURL.indexOf(','); 0494 } 0495 if (index != -1) { 0496 int len = index - 5; 0497 if (len > 0) { 0498 effectiveServiceType = effectiveURL.mid(5, len); 0499 } else { 0500 effectiveServiceType = "text/plain"; // Data URLs with no MIME type are considered text/plain. 0501 } 0502 } 0503 } 0504 0505 // Figure out if may be we're image-like. In this case, we don't need to load anything, 0506 // but may need to do a detach/attach 0507 QStringList supportedImageTypes = khtmlImLoad::ImageManager::loaderDatabase()->supportedMimeTypes(); 0508 0509 bool newImageLike = effectiveServiceType.startsWith(QLatin1String("image/")) && supportedImageTypes.contains(effectiveServiceType); 0510 0511 if (newImageLike != m_imageLike) { 0512 m_imageLike = newImageLike; 0513 requestRerender(); 0514 } 0515 0516 if (m_imageLike) { 0517 return; 0518 } 0519 0520 // Now see if we have to render alternate content. 0521 bool newRenderAlternative = false; 0522 0523 // If we aren't permitted to load this by security policy, render alternative content instead. 0524 if (!document()->isURLAllowed(effectiveURL)) { 0525 newRenderAlternative = true; 0526 } 0527 0528 // If Java is off, render alternative as well... 0529 if (effectiveServiceType == "application/x-java-applet") { 0530 KHTMLPart *p = document()->part(); 0531 if (!p || !p->javaEnabled()) { 0532 newRenderAlternative = true; 0533 } 0534 } 0535 0536 // If there is no <embed> (here or as a child), and we don't have a type + url to go on, 0537 // we need to render alternative as well 0538 if (!embed && effectiveURL.isEmpty() && effectiveServiceType.isEmpty()) { 0539 newRenderAlternative = true; 0540 } 0541 0542 if (newRenderAlternative != m_renderAlternative) { 0543 m_renderAlternative = newRenderAlternative; 0544 requestRerender(); 0545 } 0546 0547 if (m_renderAlternative) { 0548 return; 0549 } 0550 0551 KHTMLPart *part = document()->part(); 0552 clearChildWidget(); 0553 0554 // qCDebug(KHTML_LOG) << effectiveURL << effectiveServiceType << params; 0555 0556 if (!part->loadObjectElement(this, effectiveURL, effectiveServiceType, params)) { 0557 // Looks like we are gonna need alternative content after all... 0558 m_renderAlternative = true; 0559 } 0560 0561 // Either way, we need to re-attach, either for alternative content, or because 0562 // we got the part.. 0563 requestRerender(); 0564 } 0565 0566 void HTMLObjectBaseElementImpl::setWidgetNotify(QWidget *widget) 0567 { 0568 // Ick. 0569 if (m_render && strcmp(m_render->renderName(), "RenderPartObject") == 0) { 0570 static_cast<RenderPartObject *>(m_render)->setWidget(widget); 0571 } 0572 } 0573 0574 void HTMLObjectBaseElementImpl::renderAlternative() 0575 { 0576 if (m_renderAlternative) { 0577 return; 0578 } 0579 0580 m_renderAlternative = true; 0581 requestRerender(); 0582 } 0583 0584 void HTMLObjectBaseElementImpl::partLoadingErrorNotify() 0585 { 0586 // Defer ourselves from the current event loop (to prevent crashes due to the message box staying up) 0587 QTimer::singleShot(0, this, SLOT(slotPartLoadingErrorNotify())); 0588 0589 // Either way, we don't have stuff to display, so have to render alternative content. 0590 if (!m_renderAlternative) { 0591 m_renderAlternative = true; 0592 requestRerender(); 0593 } 0594 0595 clearChildWidget(); 0596 } 0597 0598 void HTMLObjectBaseElementImpl::slotPartLoadingErrorNotify() 0599 { 0600 // If we have an embed, we may be able to tell the user where to 0601 // download the plugin. 0602 0603 HTMLEmbedElementImpl *embed = relevantEmbed(); 0604 QString serviceType; // shadows ours, but we don't care. 0605 0606 if (!embed) { 0607 return; 0608 } 0609 0610 serviceType = embed->serviceType; 0611 0612 KHTMLPart *part = document()->part(); 0613 KParts::BrowserExtension *ext = part->browserExtension(); 0614 0615 if (!embed->pluginPage.isEmpty() && ext) { 0616 // Prepare the mimetype to show in the question (comment if available, name as fallback) 0617 QString mimeName = serviceType; 0618 QMimeDatabase db; 0619 QMimeType mime = db.mimeTypeForName(serviceType); 0620 if (mime.isValid()) { 0621 mimeName = mime.comment(); 0622 } 0623 0624 // Check if we already asked the user, for this page 0625 if (!mimeName.isEmpty() && !part->pluginPageQuestionAsked(serviceType)) { 0626 part->setPluginPageQuestionAsked(serviceType); 0627 0628 // Prepare the URL to show in the question (host only if http, to make it short) 0629 QUrl pluginPageURL(embed->pluginPage); 0630 QString shortURL = pluginPageURL.scheme() == "http" ? pluginPageURL.host() : pluginPageURL.toDisplayString(); 0631 int res = KMessageBox::questionTwoActions(part->view(), 0632 i18n("No plugin found for '%1'.\nDo you want to download one from %2?", mimeName, shortURL), 0633 i18n("Missing Plugin"), KGuiItem(i18n("Download")), KGuiItem(i18n("Do Not Download")), QString("plugin-") + serviceType); 0634 if (res == KMessageBox::PrimaryAction) { 0635 // Display vendor download page 0636 ext->createNewWindow(pluginPageURL); 0637 return; 0638 } 0639 } 0640 } 0641 } 0642 0643 // ------------------------------------------------------------------------- 0644 0645 HTMLAppletElementImpl::HTMLAppletElementImpl(DocumentImpl *doc) 0646 : HTMLObjectBaseElementImpl(doc) 0647 { 0648 serviceType = "application/x-java-applet"; 0649 } 0650 0651 HTMLAppletElementImpl::~HTMLAppletElementImpl() 0652 { 0653 } 0654 0655 NodeImpl::Id HTMLAppletElementImpl::id() const 0656 { 0657 return ID_APPLET; 0658 } 0659 0660 void HTMLAppletElementImpl::parseAttribute(AttributeImpl *attr) 0661 { 0662 switch (attr->id()) { 0663 case ATTR_CODEBASE: 0664 case ATTR_ARCHIVE: 0665 case ATTR_CODE: 0666 case ATTR_OBJECT: 0667 case ATTR_ALT: 0668 break; 0669 case ATTR_ALIGN: 0670 addHTMLAlignment(attr->value()); 0671 break; 0672 case ATTR_VSPACE: 0673 addCSSLength(CSS_PROP_MARGIN_TOP, attr->value()); 0674 addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value()); 0675 break; 0676 case ATTR_HSPACE: 0677 addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value()); 0678 addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value()); 0679 break; 0680 case ATTR_VALIGN: 0681 addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower()); 0682 break; 0683 default: 0684 HTMLObjectBaseElementImpl::parseAttribute(attr); 0685 } 0686 } 0687 0688 void HTMLAppletElementImpl::computeContent() 0689 { 0690 DOMString codeBase = getAttribute(ATTR_CODEBASE); 0691 DOMString code = getAttribute(ATTR_CODE); 0692 if (!codeBase.isEmpty()) { 0693 url = codeBase.string(); 0694 } 0695 if (!code.isEmpty()) { 0696 url = code.string(); 0697 } 0698 HTMLObjectBaseElementImpl::computeContent(); 0699 } 0700 0701 // ------------------------------------------------------------------------- 0702 0703 HTMLEmbedElementImpl::HTMLEmbedElementImpl(DocumentImpl *doc) 0704 : HTMLObjectBaseElementImpl(doc) 0705 { 0706 } 0707 0708 HTMLEmbedElementImpl::~HTMLEmbedElementImpl() 0709 { 0710 } 0711 0712 NodeImpl::Id HTMLEmbedElementImpl::id() const 0713 { 0714 return ID_EMBED; 0715 } 0716 0717 HTMLEmbedElementImpl *HTMLEmbedElementImpl::relevantEmbed() 0718 { 0719 return this; 0720 } 0721 0722 void HTMLEmbedElementImpl::parseAttribute(AttributeImpl *attr) 0723 { 0724 switch (attr->id()) { 0725 case ATTR_CODE: 0726 case ATTR_SRC: 0727 url = attr->value().trimSpaces().string(); 0728 setNeedComputeContent(); 0729 break; 0730 case ATTR_BORDER: 0731 addCSSLength(CSS_PROP_BORDER_WIDTH, attr->value()); 0732 addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID); 0733 addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID); 0734 addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID); 0735 addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID); 0736 break; 0737 case ATTR_VSPACE: 0738 addCSSLength(CSS_PROP_MARGIN_TOP, attr->value()); 0739 addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value()); 0740 break; 0741 case ATTR_HSPACE: 0742 addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value()); 0743 addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value()); 0744 break; 0745 case ATTR_ALIGN: 0746 addHTMLAlignment(attr->value()); 0747 break; 0748 case ATTR_VALIGN: 0749 addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower()); 0750 break; 0751 case ATTR_PLUGINPAGE: 0752 case ATTR_PLUGINSPAGE: { 0753 pluginPage = attr->value().string(); 0754 break; 0755 } 0756 case ATTR_HIDDEN: 0757 if (strcasecmp(attr->value(), "yes") == 0 || strcasecmp(attr->value(), "true") == 0) { 0758 hidden = true; 0759 } else { 0760 hidden = false; 0761 } 0762 break; 0763 default: 0764 HTMLObjectBaseElementImpl::parseAttribute(attr); 0765 } 0766 } 0767 0768 void HTMLEmbedElementImpl::attach() 0769 { 0770 if (parentNode()->id() == ID_OBJECT) { 0771 NodeBaseImpl::attach(); 0772 } else { 0773 HTMLObjectBaseElementImpl::attach(); 0774 } 0775 } 0776 0777 void HTMLEmbedElementImpl::computeContent() 0778 { 0779 if (parentNode()->id() != ID_OBJECT) { 0780 HTMLObjectBaseElementImpl::computeContent(); 0781 } 0782 } 0783 0784 // ------------------------------------------------------------------------- 0785 0786 HTMLObjectElementImpl::HTMLObjectElementImpl(DocumentImpl *doc) 0787 : HTMLObjectBaseElementImpl(doc) 0788 { 0789 } 0790 0791 HTMLObjectElementImpl::~HTMLObjectElementImpl() 0792 { 0793 } 0794 0795 NodeImpl::Id HTMLObjectElementImpl::id() const 0796 { 0797 return ID_OBJECT; 0798 } 0799 0800 HTMLFormElementImpl *HTMLObjectElementImpl::form() const 0801 { 0802 return nullptr; 0803 } 0804 0805 void HTMLObjectElementImpl::parseAttribute(AttributeImpl *attr) 0806 { 0807 switch (attr->id()) { 0808 case ATTR_DATA: 0809 url = attr->value().trimSpaces().string(); 0810 setNeedComputeContent(); 0811 break; 0812 case ATTR_CLASSID: 0813 classId = attr->value().string(); 0814 setNeedComputeContent(); 0815 break; 0816 case ATTR_ONLOAD: // ### support load/unload on object elements 0817 setHTMLEventListener(EventImpl::LOAD_EVENT, 0818 document()->createHTMLEventListener(attr->value().string(), "onload", this)); 0819 break; 0820 case ATTR_ONUNLOAD: 0821 setHTMLEventListener(EventImpl::UNLOAD_EVENT, 0822 document()->createHTMLEventListener(attr->value().string(), "onunload", this)); 0823 break; 0824 case ATTR_VSPACE: 0825 addCSSLength(CSS_PROP_MARGIN_TOP, attr->value()); 0826 addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value()); 0827 break; 0828 case ATTR_HSPACE: 0829 addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value()); 0830 addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value()); 0831 break; 0832 case ATTR_ALIGN: 0833 addHTMLAlignment(attr->value()); 0834 break; 0835 case ATTR_VALIGN: 0836 addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower()); 0837 break; 0838 default: 0839 HTMLObjectBaseElementImpl::parseAttribute(attr); 0840 } 0841 } 0842 0843 DocumentImpl *HTMLObjectElementImpl::contentDocument() const 0844 { 0845 QWidget *widget = childWidget(); 0846 if (widget && qobject_cast<KHTMLView *>(widget)) { 0847 return static_cast<KHTMLView *>(widget)->part()->xmlDocImpl(); 0848 } 0849 return nullptr; 0850 } 0851 0852 void HTMLObjectElementImpl::attach() 0853 { 0854 HTMLObjectBaseElementImpl::attach(); 0855 } 0856 0857 // ------------------------------------------------------------------------- 0858 0859 NodeImpl::Id HTMLParamElementImpl::id() const 0860 { 0861 return ID_PARAM; 0862 } 0863 0864 void HTMLParamElementImpl::parseAttribute(AttributeImpl *attr) 0865 { 0866 switch (attr->id()) { 0867 case ATTR_VALUE: 0868 m_value = attr->value().string(); 0869 break; 0870 case ATTR_ID: 0871 if (document()->htmlMode() != DocumentImpl::XHtml) { 0872 break; 0873 } 0874 // fall through 0875 case ATTR_NAME: 0876 m_name = attr->value().string(); 0877 // fall through 0878 default: 0879 HTMLElementImpl::parseAttribute(attr); 0880 } 0881 } 0882 0883 #include "moc_html_objectimpl.cpp"