diff options
author | Kristian Monsen <kristianm@google.com> | 2010-09-08 12:18:00 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-09-11 12:08:58 +0100 |
commit | 5ddde30071f639962dd557c453f2ad01f8f0fd00 (patch) | |
tree | 775803c4ab35af50aa5f5472cd1fb95fe9d5152d /WebCore/rendering/RenderEmbeddedObject.cpp | |
parent | 3e63d9b33b753ca86d0765d1b3d711114ba9e34f (diff) | |
download | external_webkit-5ddde30071f639962dd557c453f2ad01f8f0fd00.zip external_webkit-5ddde30071f639962dd557c453f2ad01f8f0fd00.tar.gz external_webkit-5ddde30071f639962dd557c453f2ad01f8f0fd00.tar.bz2 |
Merge WebKit at r66666 : Initial merge by git.
Change-Id: I57dedeb49859adc9c539e760f0e749768c66626f
Diffstat (limited to 'WebCore/rendering/RenderEmbeddedObject.cpp')
-rw-r--r-- | WebCore/rendering/RenderEmbeddedObject.cpp | 331 |
1 files changed, 175 insertions, 156 deletions
diff --git a/WebCore/rendering/RenderEmbeddedObject.cpp b/WebCore/rendering/RenderEmbeddedObject.cpp index 55b230b..b1b253a 100644 --- a/WebCore/rendering/RenderEmbeddedObject.cpp +++ b/WebCore/rendering/RenderEmbeddedObject.cpp @@ -102,6 +102,7 @@ bool RenderEmbeddedObject::allowsAcceleratedCompositing() const } #endif +// FIXME: This belongs in HTMLPluginElement.cpp to be shared by HTMLObjectElement and HTMLEmbedElement. static bool isURLAllowed(Document* doc, const String& url) { if (doc->frame()->page()->frameCount() >= Page::maxNumberOfFrames) @@ -123,6 +124,7 @@ static bool isURLAllowed(Document* doc, const String& url) typedef HashMap<String, String, CaseFoldingHash> ClassIdToTypeMap; +// FIXME: This belongs in HTMLObjectElement.cpp static ClassIdToTypeMap* createClassIdToTypeMap() { ClassIdToTypeMap* map = new ClassIdToTypeMap; @@ -135,6 +137,7 @@ static ClassIdToTypeMap* createClassIdToTypeMap() return map; } +// FIXME: This belongs in HTMLObjectElement.cpp static String serviceTypeForClassId(const String& classId) { // Return early if classId is empty (since we won't do anything below). @@ -146,6 +149,7 @@ static String serviceTypeForClassId(const String& classId) return map->get(classId); } +// FIXME: This belongs in HTMLObjectElement.cpp static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramValues) { // Some plugins don't understand the "data" attribute of the OBJECT tag (i.e. Real and WMP @@ -164,190 +168,205 @@ static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramV } } -void RenderEmbeddedObject::updateWidget(bool onlyCreateNonNetscapePlugins) +// FIXME: This belongs in some loader header? +static bool isNetscapePlugin(Frame* frame, const String& url, const String& serviceType) { - if (!m_replacementText.isNull() || !node()) // Check the node in case destroy() has been called. - return; - - String url; - String serviceType; - Vector<String> paramNames; - Vector<String> paramValues; - Frame* frame = frameView()->frame(); - - // The calls to SubframeLoader::requestObject within this function can result in a plug-in being initialized. - // This can run cause arbitrary JavaScript to run and may result in this RenderObject being detached from - // the render tree and destroyed, causing a crash like <rdar://problem/6954546>. By extending our lifetime - // artifically to ensure that we remain alive for the duration of plug-in initialization. - RenderWidgetProtector protector(this); + KURL completedURL; + if (!url.isEmpty()) + completedURL = frame->loader()->completeURL(url); - if (node()->hasTagName(objectTag)) { - HTMLObjectElement* objectElement = static_cast<HTMLObjectElement*>(node()); + if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) + return true; + return false; +} - objectElement->setNeedWidgetUpdate(false); - if (!objectElement->isFinishedParsingChildren()) - return; +// FIXME: This belongs on HTMLObjectElement. +static bool hasFallbackContent(HTMLObjectElement* objectElement) +{ + for (Node* child = objectElement->firstChild(); child; child = child->nextSibling()) { + if ((!child->isTextNode() && !child->hasTagName(paramTag)) // Discount <param> + || (child->isTextNode() && !static_cast<Text*>(child)->containsOnlyWhitespace())) + return true; + } + return false; +} - // Check for a child EMBED tag. - HTMLEmbedElement* embed = 0; - for (Node* child = objectElement->firstChild(); child; ) { - if (child->hasTagName(embedTag)) { - embed = static_cast<HTMLEmbedElement*>(child); - break; +// FIXME: This belongs on HTMLObjectElement. +static void parametersFromObject(HTMLObjectElement* objectElement, Vector<String>& paramNames, Vector<String>& paramValues, String& url, String& serviceType) +{ + HashSet<StringImpl*, CaseFoldingHash> uniqueParamNames; + + // Scan the PARAM children and store their name/value pairs. + // Get the URL and type from the params if we don't already have them. + Node* child = objectElement->firstChild(); + while (child) { + if (child->hasTagName(paramTag)) { + HTMLParamElement* p = static_cast<HTMLParamElement*>(child); + String name = p->name(); + if (url.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url"))) + url = deprecatedParseURL(p->value()); + // FIXME: serviceType calculation does not belong in this function. + if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) { + serviceType = p->value(); + size_t pos = serviceType.find(";"); + if (pos != notFound) + serviceType = serviceType.left(pos); } - - if (child->hasTagName(objectTag)) - child = child->nextSibling(); // Don't descend into nested OBJECT tags - else - child = child->traverseNextNode(objectElement); // 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 = embed; - url = embed->url(); - serviceType = embed->serviceType(); - } else - embedOrObject = objectElement; - - // If there was no URL or type defined in EMBED, try the OBJECT tag. - if (url.isEmpty()) - url = objectElement->url(); - if (serviceType.isEmpty()) - serviceType = objectElement->serviceType(); - - HashSet<StringImpl*, CaseFoldingHash> 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 = objectElement->firstChild(); - while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) { - if (child->hasTagName(paramTag)) { - HTMLParamElement* p = static_cast<HTMLParamElement*>(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(); - size_t pos = serviceType.find(";"); - if (pos != notFound) - serviceType = serviceType.left(pos); - } - if (!embed && !name.isEmpty()) { - uniqueParamNames.add(name.impl()); - paramNames.append(p->name()); - paramValues.append(p->value()); - } + if (!name.isEmpty()) { + uniqueParamNames.add(name.impl()); + paramNames.append(p->name()); + paramValues.append(p->value()); } - child = child->nextSibling(); } + 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 <http://java.sun.com/products/plugin/1.2/docs/tags.html>. 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. - NamedNodeMap* 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()); - } + // 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 <http://java.sun.com/products/plugin/1.2/docs/tags.html>. 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 (MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) { + codebase = "codebase"; + uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already + } + + // Turn the attributes of the <object> element into arrays, but don't override <param> values. + NamedNodeMap* attributes = objectElement->attributes(); + if (attributes) { + for (unsigned i = 0; i < attributes->length(); ++i) { + Attribute* it = attributes->attributeItem(i); + const AtomicString& name = it->name().localName(); + if (!uniqueParamNames.contains(name.impl())) { + paramNames.append(name.string()); + paramValues.append(it->value().string()); } } + } - mapDataParamToSrc(¶mNames, ¶mValues); + mapDataParamToSrc(¶mNames, ¶mValues); - // If we still don't have a type, try to map from a specific CLASSID to a type. - if (serviceType.isEmpty()) - serviceType = serviceTypeForClassId(objectElement->classId()); + // If we still don't have a type, try to map from a specific CLASSID to a type. + if (serviceType.isEmpty()) + serviceType = serviceTypeForClassId(objectElement->classId()); +} - if (!isURLAllowed(document(), url)) - return; +// FIXME: This belongs on HTMLObjectElement, HTMLPluginElement or HTMLFrameOwnerElement. +static void updateWidgetForObjectElement(HTMLObjectElement* objectElement, bool onlyCreateNonNetscapePlugins) +{ + objectElement->setNeedsWidgetUpdate(false); + if (!objectElement->isFinishedParsingChildren()) + return; - // Find out if we support fallback content. - m_hasFallbackContent = false; - for (Node* child = objectElement->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) { - if ((!child->isTextNode() && !child->hasTagName(embedTag) && !child->hasTagName(paramTag)) // Discount <embed> and <param> - || (child->isTextNode() && !static_cast<Text*>(child)->containsOnlyWhitespace())) - m_hasFallbackContent = true; - } + Frame* frame = objectElement->document()->frame(); + String url = objectElement->url(); + String serviceType = objectElement->serviceType(); - if (onlyCreateNonNetscapePlugins) { - KURL completedURL; - if (!url.isEmpty()) - completedURL = frame->loader()->completeURL(url); + Vector<String> paramNames; + Vector<String> paramValues; + parametersFromObject(objectElement, paramNames, paramValues, url, serviceType); - if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) - return; - } + if (!isURLAllowed(objectElement->document(), url)) + return; - bool beforeLoadAllowedLoad = objectElement->dispatchBeforeLoadEvent(url); - - // beforeload events can modify the DOM, potentially causing - // RenderWidget::destroy() to be called. Ensure we haven't been - // destroyed before continuing. - if (!node()) - return; - - bool success = beforeLoadAllowedLoad && frame->loader()->subframeLoader()->requestObject(this, url, objectElement->getAttribute(nameAttr), serviceType, paramNames, paramValues); - - if (!success && m_hasFallbackContent) - objectElement->renderFallbackContent(); + bool fallbackContent = hasFallbackContent(objectElement); + objectElement->renderEmbeddedObject()->setHasFallbackContent(fallbackContent); - } else if (node()->hasTagName(embedTag)) { - HTMLEmbedElement* embedElement = static_cast<HTMLEmbedElement*>(node()); - embedElement->setNeedWidgetUpdate(false); - url = embedElement->url(); - serviceType = embedElement->serviceType(); + if (onlyCreateNonNetscapePlugins && isNetscapePlugin(frame, url, serviceType)) + return; - if (url.isEmpty() && serviceType.isEmpty()) - return; - if (!isURLAllowed(document(), url)) - return; + bool beforeLoadAllowedLoad = objectElement->dispatchBeforeLoadEvent(url); - // add all attributes set on the embed object - NamedNodeMap* attributes = embedElement->attributes(); - if (attributes) { - for (unsigned i = 0; i < attributes->length(); ++i) { - Attribute* it = attributes->attributeItem(i); - paramNames.append(it->name().localName().string()); - paramValues.append(it->value().string()); - } - } + // beforeload events can modify the DOM, potentially causing + // RenderWidget::destroy() to be called. Ensure we haven't been + // destroyed before continuing. + // FIXME: Should this render fallback content? + if (!objectElement->renderer()) + return; + + bool success = beforeLoadAllowedLoad && frame->loader()->subframeLoader()->requestObject(objectElement, url, objectElement->getAttribute(nameAttr), serviceType, paramNames, paramValues); - if (onlyCreateNonNetscapePlugins) { - KURL completedURL; - if (!url.isEmpty()) - completedURL = frame->loader()->completeURL(url); + if (!success && fallbackContent) + objectElement->renderFallbackContent(); +} - if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin) - return; +// FIXME: This belongs on HTMLEmbedElement. +static void parametersFromEmbed(HTMLEmbedElement* embedElement, Vector<String>& paramNames, Vector<String>& paramValues) +{ + NamedNodeMap* attributes = embedElement->attributes(); + if (attributes) { + for (unsigned i = 0; i < attributes->length(); ++i) { + Attribute* it = attributes->attributeItem(i); + paramNames.append(it->name().localName().string()); + paramValues.append(it->value().string()); } + } +} + +// FIXME: This belongs on HTMLEmbedElement, HTMLPluginElement or HTMLFrameOwnerElement. +static void updateWidgetForEmbedElement(HTMLEmbedElement* embedElement, bool onlyCreateNonNetscapePlugins) +{ + Frame* frame = embedElement->document()->frame(); + String url = embedElement->url(); + String serviceType = embedElement->serviceType(); - if (embedElement->dispatchBeforeLoadEvent(url)) - frame->loader()->subframeLoader()->requestObject(this, url, embedElement->getAttribute(nameAttr), serviceType, paramNames, paramValues); + embedElement->setNeedsWidgetUpdate(false); + + if (url.isEmpty() && serviceType.isEmpty()) + return; + if (!isURLAllowed(embedElement->document(), url)) + return; + + Vector<String> paramNames; + Vector<String> paramValues; + parametersFromEmbed(embedElement, paramNames, paramValues); + + if (onlyCreateNonNetscapePlugins && isNetscapePlugin(frame, url, serviceType)) + return; + + if (embedElement->dispatchBeforeLoadEvent(url)) { + // FIXME: beforeLoad could have detached the renderer! Just like in the <object> case above. + frame->loader()->subframeLoader()->requestObject(embedElement, url, embedElement->getAttribute(nameAttr), serviceType, paramNames, paramValues); + } +} + +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +// FIXME: This belongs on HTMLMediaElement. +static void updateWidgetForMediaElement(HTMLMediaElement* mediaElement, bool ignored) +{ + Vector<String> paramNames; + Vector<String> paramValues; + KURL kurl; + + mediaElement->getPluginProxyParams(kurl, paramNames, paramValues); + mediaElement->setNeedWidgetUpdate(false); + frame->loader()->subframeLoader()->loadMediaPlayerProxyPlugin(mediaElement, kurl, paramNames, paramValues); +} +#endif + +void RenderEmbeddedObject::updateWidget(bool onlyCreateNonNetscapePlugins) +{ + if (!m_replacementText.isNull() || !node()) // Check the node in case destroy() has been called. + return; + + // The calls to SubframeLoader::requestObject within this function can result in a plug-in being initialized. + // This can run cause arbitrary JavaScript to run and may result in this RenderObject being detached from + // the render tree and destroyed, causing a crash like <rdar://problem/6954546>. By extending our lifetime + // artifically to ensure that we remain alive for the duration of plug-in initialization. + RenderWidgetProtector protector(this); + + if (node()->hasTagName(objectTag)) { + HTMLObjectElement* objectElement = static_cast<HTMLObjectElement*>(node()); + updateWidgetForObjectElement(objectElement, onlyCreateNonNetscapePlugins); + } else if (node()->hasTagName(embedTag)) { + HTMLEmbedElement* embedElement = static_cast<HTMLEmbedElement*>(node()); + updateWidgetForEmbedElement(embedElement, onlyCreateNonNetscapePlugins); } #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) else if (node()->hasTagName(videoTag) || node()->hasTagName(audioTag)) { HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node()); - KURL kurl; - - mediaElement->getPluginProxyParams(kurl, paramNames, paramValues); - mediaElement->setNeedWidgetUpdate(false); - frame->loader()->subframeLoader()->loadMediaPlayerProxyPlugin(node(), kurl, paramNames, paramValues); + updateWidgetForMediaElement(mediaElement, onlyCreateNonNetscapePlugins); } #endif } |