summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering/RenderEmbeddedObject.cpp
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-09-08 12:18:00 +0100
committerKristian Monsen <kristianm@google.com>2010-09-11 12:08:58 +0100
commit5ddde30071f639962dd557c453f2ad01f8f0fd00 (patch)
tree775803c4ab35af50aa5f5472cd1fb95fe9d5152d /WebCore/rendering/RenderEmbeddedObject.cpp
parent3e63d9b33b753ca86d0765d1b3d711114ba9e34f (diff)
downloadexternal_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.cpp331
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(&paramNames, &paramValues);
+ mapDataParamToSrc(&paramNames, &paramValues);
- // 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
}