From 635860845790a19bf50bbc51ba8fb66a96dde068 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Thu, 5 Mar 2009 14:34:32 -0800 Subject: auto import from //depot/cupcake/@136594 --- WebCore/rendering/RenderPartObject.cpp | 394 ++++++++++++++++++--------------- 1 file changed, 217 insertions(+), 177 deletions(-) (limited to 'WebCore/rendering/RenderPartObject.cpp') diff --git a/WebCore/rendering/RenderPartObject.cpp b/WebCore/rendering/RenderPartObject.cpp index 75ecdec..86cb2ad 100644 --- a/WebCore/rendering/RenderPartObject.cpp +++ b/WebCore/rendering/RenderPartObject.cpp @@ -36,6 +36,8 @@ #include "HTMLParamElement.h" #include "MIMETypeRegistry.h" #include "Page.h" +#include "PluginData.h" +#include "RenderView.h" #include "Text.h" #ifdef FLATTEN_IFRAME @@ -52,6 +54,9 @@ RenderPartObject::RenderPartObject(HTMLFrameOwnerElement* element) // init RenderObject attributes setInline(true); m_hasFallbackContent = false; + + if (element->hasTagName(embedTag) || element->hasTagName(objectTag)) + view()->frameView()->setIsVisuallyNonEmpty(); } RenderPartObject::~RenderPartObject() @@ -79,183 +84,216 @@ static bool isURLAllowed(Document* doc, const String& url) return true; } -static inline void mapClassIdToServiceType(const String& classId, String& serviceType) +typedef HashMap ClassIdToTypeMap; + +static ClassIdToTypeMap* createClassIdToTypeMap() { - // It is ActiveX, but the nsplugin system handling - // should also work, that's why we don't override the - // serviceType with application/x-activex-handler - // but let the KTrader in khtmlpart::createPart() detect - // the user's preference: launch with activex viewer or - // with nspluginviewer (Niko) - if (classId.contains("D27CDB6E-AE6D-11cf-96B8-444553540000")) - serviceType = "application/x-shockwave-flash"; - else if (classId.contains("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) - serviceType = "audio/x-pn-realaudio-plugin"; - else if (classId.contains("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) - serviceType = "video/quicktime"; - else if (classId.contains("166B1BCA-3F9C-11CF-8075-444553540000")) - serviceType = "application/x-director"; - else if (classId.contains("6BF52A52-394A-11d3-B153-00C04F79FAA6")) - serviceType = "application/x-mplayer2"; - else if (!classId.isEmpty()) { - // We have a clsid, means this is Active X (Niko) - serviceType = "application/x-activex-handler"; - } + ClassIdToTypeMap* map = new ClassIdToTypeMap; + map->add("clsid:D27CDB6E-AE6D-11CF-96B8-444553540000", "application/x-shockwave-flash"); + map->add("clsid:CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA", "audio/x-pn-realaudio-plugin"); + map->add("clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B", "video/quicktime"); + map->add("clsid:166B1BCA-3F9C-11CF-8075-444553540000", "application/x-director"); +#if ENABLE(ACTIVEX_TYPE_CONVERSION_WMPLAYER) + map->add("clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6", "application/x-mplayer2"); + map->add("clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95", "application/x-mplayer2"); +#endif + return map; +} + +static const String& activeXType() +{ + DEFINE_STATIC_LOCAL(String, activeXType, ("application/x-oleobject")); + return activeXType; +} + +static inline bool havePlugin(const PluginData* pluginData, const String& type) +{ + return pluginData && !type.isEmpty() && pluginData->supportsMimeType(type); +} + +static String serviceTypeForClassId(const String& classId, const PluginData* pluginData) +{ + // Return early if classId is empty (since we won't do anything below). + // Furthermore, if classId is null, calling get() below will crash. + if (classId.isEmpty()) + return String(); + + static ClassIdToTypeMap* map = createClassIdToTypeMap(); + String type = map->get(classId); + + // If we do have a plug-in that supports generic ActiveX content and don't have a plug-in + // for the MIME type we came up with, ignore the MIME type we came up with and just use + // the ActiveX type. + if (havePlugin(pluginData, activeXType()) && !havePlugin(pluginData, type)) + return activeXType(); + + return type; +} + +static inline bool shouldUseEmbedDescendant(HTMLObjectElement* objectElement, const PluginData* pluginData) +{ + // If we have both an and , we always want to use the except when we have + // an ActiveX plug-in and plan to use it. + return !(havePlugin(pluginData, activeXType()) + && serviceTypeForClassId(objectElement->classId(), pluginData) == activeXType()); } void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) { - String url; - String serviceType; - Vector paramNames; - Vector paramValues; - Frame* frame = m_view->frame(); - - if (element()->hasTagName(objectTag)) { - - HTMLObjectElement* o = static_cast(element()); - - o->setNeedWidgetUpdate(false); - if (!o->isFinishedParsingChildren()) - return; - // Check for a child EMBED tag. - HTMLEmbedElement* embed = 0; - for (Node* child = o->firstChild(); child;) { - if (child->hasTagName(embedTag)) { - embed = static_cast(child); - break; - } else if (child->hasTagName(objectTag)) - child = child->nextSibling(); // Don't descend into nested OBJECT tags - else - child = child->traverseNextNode(o); // Otherwise descend (EMBEDs may be inside COMMENT tags) - } - - // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT. - HTMLElement *embedOrObject; - if (embed) { - embedOrObject = (HTMLElement *)embed; - url = embed->url(); - serviceType = embed->serviceType(); - } else - embedOrObject = (HTMLElement *)o; - - // If there was no URL or type defined in EMBED, try the OBJECT tag. - if (url.isEmpty()) - url = o->url(); - if (serviceType.isEmpty()) - serviceType = o->serviceType(); - - HashSet uniqueParamNames; - - // Scan the PARAM children. - // Get the URL and type from the params if we don't already have them. - // Get the attributes from the params if there is no EMBED tag. - Node *child = o->firstChild(); - while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) { - if (child->hasTagName(paramTag)) { - HTMLParamElement* p = static_cast(child); - String name = p->name(); - if (url.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url"))) - url = p->value(); - if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) { - serviceType = p->value(); - int pos = serviceType.find(";"); - if (pos != -1) - serviceType = serviceType.left(pos); - } - if (!embed && !name.isEmpty()) { - uniqueParamNames.add(name.impl()); - paramNames.append(p->name()); - paramValues.append(p->value()); - } - } - child = child->nextSibling(); - } - - // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag - // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is - // in a PARAM tag. See . This means - // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM, - // else our Java plugin will misinterpret it. [4004531] - String codebase; - if (!embed && MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) { - codebase = "codebase"; - uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already - } - - // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values. - NamedAttrMap* attributes = embedOrObject->attributes(); - if (attributes) { - for (unsigned i = 0; i < attributes->length(); ++i) { - Attribute* it = attributes->attributeItem(i); - const AtomicString& name = it->name().localName(); - if (embed || !uniqueParamNames.contains(name.impl())) { - paramNames.append(name.string()); - paramValues.append(it->value().string()); - } - } - } - - // If we still don't have a type, try to map from a specific CLASSID to a type. - if (serviceType.isEmpty() && !o->classId().isEmpty()) - mapClassIdToServiceType(o->classId(), serviceType); - - if (!isURLAllowed(document(), url)) + String url; + String serviceType; + Vector paramNames; + Vector paramValues; + Frame* frame = m_view->frame(); + + if (element()->hasTagName(objectTag)) { + HTMLObjectElement* o = static_cast(element()); + + o->setNeedWidgetUpdate(false); + if (!o->isFinishedParsingChildren()) return; - // Find out if we support fallback content. - m_hasFallbackContent = false; - for (Node *child = o->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) { - if ((!child->isTextNode() && !child->hasTagName(embedTag) && !child->hasTagName(paramTag)) || // Discount and - (child->isTextNode() && !static_cast(child)->containsOnlyWhitespace())) - m_hasFallbackContent = true; - } - - if (onlyCreateNonNetscapePlugins) { - KURL completedURL; - if (!url.isEmpty()) - completedURL = frame->loader()->completeURL(url); + // Check for a child EMBED tag. + HTMLEmbedElement* embed = 0; + const PluginData* pluginData = frame->page()->pluginData(); + if (shouldUseEmbedDescendant(o, pluginData)) { + for (Node* child = o->firstChild(); child; ) { + if (child->hasTagName(embedTag)) { + embed = static_cast(child); + break; + } else if (child->hasTagName(objectTag)) + child = child->nextSibling(); // Don't descend into nested OBJECT tags + else + child = child->traverseNextNode(o); // Otherwise descend (EMBEDs may be inside COMMENT tags) + } + } + + // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT. + HTMLElement *embedOrObject; + if (embed) { + embedOrObject = (HTMLElement *)embed; + url = embed->url(); + serviceType = embed->serviceType(); + } else + embedOrObject = (HTMLElement *)o; + + // If there was no URL or type defined in EMBED, try the OBJECT tag. + if (url.isEmpty()) + url = o->url(); + if (serviceType.isEmpty()) + serviceType = o->serviceType(); + + HashSet uniqueParamNames; + + // Scan the PARAM children. + // Get the URL and type from the params if we don't already have them. + // Get the attributes from the params if there is no EMBED tag. + Node *child = o->firstChild(); + while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) { + if (child->hasTagName(paramTag)) { + HTMLParamElement* p = static_cast(child); + String name = p->name(); + if (url.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url"))) + url = p->value(); + if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) { + serviceType = p->value(); + int pos = serviceType.find(";"); + if (pos != -1) + serviceType = serviceType.left(pos); + } + if (!embed && !name.isEmpty()) { + uniqueParamNames.add(name.impl()); + paramNames.append(p->name()); + paramValues.append(p->value()); + } + } + child = child->nextSibling(); + } + + // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag + // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is + // in a PARAM tag. See . This means + // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM, + // else our Java plugin will misinterpret it. [4004531] + String codebase; + if (!embed && MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) { + codebase = "codebase"; + uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already + } - if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) - return; - } - - bool success = frame->loader()->requestObject(this, url, AtomicString(o->name()), serviceType, paramNames, paramValues); - if (!success && m_hasFallbackContent) - o->renderFallbackContent(); - } else if (element()->hasTagName(embedTag)) { - HTMLEmbedElement *o = static_cast(element()); - o->setNeedWidgetUpdate(false); - url = o->url(); - serviceType = o->serviceType(); - - if (url.isEmpty() && serviceType.isEmpty()) - return; - if (!isURLAllowed(document(), url)) - return; - - // add all attributes set on the embed object - NamedAttrMap* a = o->attributes(); - if (a) { - for (unsigned i = 0; i < a->length(); ++i) { - Attribute* it = a->attributeItem(i); - paramNames.append(it->name().localName().string()); - paramValues.append(it->value().string()); - } - } - - if (onlyCreateNonNetscapePlugins) { - KURL completedURL; - if (!url.isEmpty()) - completedURL = frame->loader()->completeURL(url); - - if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) - return; - - } - - frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues); - } + // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values. + NamedAttrMap* attributes = embedOrObject->attributes(); + if (attributes) { + for (unsigned i = 0; i < attributes->length(); ++i) { + Attribute* it = attributes->attributeItem(i); + const AtomicString& name = it->name().localName(); + if (embed || !uniqueParamNames.contains(name.impl())) { + paramNames.append(name.string()); + paramValues.append(it->value().string()); + } + } + } + + // If we still don't have a type, try to map from a specific CLASSID to a type. + if (serviceType.isEmpty()) + serviceType = serviceTypeForClassId(o->classId(), pluginData); + + if (!isURLAllowed(document(), url)) + return; + + // Find out if we support fallback content. + m_hasFallbackContent = false; + for (Node *child = o->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) { + if ((!child->isTextNode() && !child->hasTagName(embedTag) && !child->hasTagName(paramTag)) || // Discount and + (child->isTextNode() && !static_cast(child)->containsOnlyWhitespace())) + m_hasFallbackContent = true; + } + + if (onlyCreateNonNetscapePlugins) { + KURL completedURL; + if (!url.isEmpty()) + completedURL = frame->loader()->completeURL(url); + + if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) + return; + } + + bool success = frame->loader()->requestObject(this, url, AtomicString(o->name()), serviceType, paramNames, paramValues); + if (!success && m_hasFallbackContent) + o->renderFallbackContent(); + } else if (element()->hasTagName(embedTag)) { + HTMLEmbedElement *o = static_cast(element()); + o->setNeedWidgetUpdate(false); + url = o->url(); + serviceType = o->serviceType(); + + if (url.isEmpty() && serviceType.isEmpty()) + return; + if (!isURLAllowed(document(), url)) + return; + + // add all attributes set on the embed object + NamedAttrMap* a = o->attributes(); + if (a) { + for (unsigned i = 0; i < a->length(); ++i) { + Attribute* it = a->attributeItem(i); + paramNames.append(it->name().localName().string()); + paramValues.append(it->value().string()); + } + } + + if (onlyCreateNonNetscapePlugins) { + KURL completedURL; + if (!url.isEmpty()) + completedURL = frame->loader()->completeURL(url); + + if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) + return; + + } + + frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues); + } } void RenderPartObject::layout() @@ -268,8 +306,10 @@ void RenderPartObject::layout() #ifdef FLATTEN_IFRAME // Some IFrames have a width and/or height of 1 when they are meant to be // hidden. If that is the case, don't try to expand. + int w = width(); + int h = height(); if (m_widget && m_widget->isFrameView() && - m_width > 1 && m_height > 1) { + w > 1 && h > 1) { FrameView* view = static_cast(m_widget); RenderView* root = NULL; if (view->frame() && view->frame()->document() && @@ -280,12 +320,12 @@ void RenderPartObject::layout() updateWidgetPosition(); // Use the preferred width if it is larger. - m_width = max(m_width, root->minPrefWidth()); + setWidth(max(w, root->minPrefWidth())); int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight(); int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom(); // Resize the view to recalc the height. - int height = m_height - extraHeight; - int width = m_width - extraWidth; + int height = h - extraHeight; + int width = w - extraWidth; if (width > view->width()) height = 0; if (width != view->width() || height != view->height()) { @@ -298,9 +338,9 @@ void RenderPartObject::layout() int contentHeight = view->contentsHeight(); int contentWidth = view->contentsWidth(); // Do not shrink iframes with specified sizes - if (contentHeight > m_height || style()->height().isAuto()) - m_height = contentHeight; - m_width = std::min(contentWidth, 800); + if (contentHeight > h || style()->height().isAuto()) + setHeight(contentHeight); + setWidth(std::min(contentWidth, 800)); } } #endif @@ -310,7 +350,7 @@ void RenderPartObject::layout() if (!m_widget && m_view) m_view->addWidgetToUpdate(this); - + setNeedsLayout(false); } -- cgit v1.1