This source file includes following definitions.
- m_useFallbackContent
- create
- existingRenderWidget
- isPresentationAttribute
- collectStyleForPresentationAttribute
- parseAttribute
- mapDataParamToSrc
- parametersForPlugin
- hasFallbackContent
- shouldAllowQuickTimeClassIdQuirk
- hasValidClassId
- reloadPluginOnAttributeChange
- updateWidgetInternal
- rendererIsNeeded
- insertedInto
- removedFrom
- childrenChanged
- isURLAttribute
- hasLegalLinkAttribute
- subResourceAttributeName
- imageSourceURL
- reattachFallbackContent
- renderFallbackContent
- isExposed
- containsJavaApplet
- didMoveToNewDocument
- appendFormData
- formOwner
- isInteractiveContent
- useFallbackContent
#include "config.h"
#include "core/html/HTMLObjectElement.h"
#include "HTMLNames.h"
#include "bindings/v8/ScriptEventListener.h"
#include "core/dom/Attribute.h"
#include "core/dom/ElementTraversal.h"
#include "core/dom/Text.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/fetch/ImageResource.h"
#include "core/html/FormDataList.h"
#include "core/html/HTMLCollection.h"
#include "core/html/HTMLDocument.h"
#include "core/html/HTMLImageLoader.h"
#include "core/html/HTMLMetaElement.h"
#include "core/html/HTMLParamElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/frame/Settings.h"
#include "core/plugins/PluginView.h"
#include "core/rendering/RenderEmbeddedObject.h"
#include "platform/MIMETypeRegistry.h"
#include "platform/Widget.h"
namespace WebCore {
using namespace HTMLNames;
inline HTMLObjectElement::HTMLObjectElement(Document& document, HTMLFormElement* form, bool createdByParser)
: HTMLPlugInElement(objectTag, document, createdByParser, ShouldNotPreferPlugInsForImages)
, m_useFallbackContent(false)
{
ScriptWrappable::init(this);
associateByParser(form);
}
inline HTMLObjectElement::~HTMLObjectElement()
{
setForm(0);
}
PassRefPtr<HTMLObjectElement> HTMLObjectElement::create(Document& document, HTMLFormElement* form, bool createdByParser)
{
RefPtr<HTMLObjectElement> element = adoptRef(new HTMLObjectElement(document, form, createdByParser));
element->ensureUserAgentShadowRoot();
return element.release();
}
RenderWidget* HTMLObjectElement::existingRenderWidget() const
{
return renderPart();
}
bool HTMLObjectElement::isPresentationAttribute(const QualifiedName& name) const
{
if (name == borderAttr)
return true;
return HTMLPlugInElement::isPresentationAttribute(name);
}
void HTMLObjectElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
{
if (name == borderAttr)
applyBorderAttributeToStyle(value, style);
else
HTMLPlugInElement::collectStyleForPresentationAttribute(name, value, style);
}
void HTMLObjectElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
if (name == formAttr)
formAttributeChanged();
else if (name == typeAttr) {
m_serviceType = value.lower();
size_t pos = m_serviceType.find(";");
if (pos != kNotFound)
m_serviceType = m_serviceType.left(pos);
reloadPluginOnAttributeChange(name);
if (!renderer())
requestPluginCreationWithoutRendererIfPossible();
} else if (name == dataAttr) {
m_url = stripLeadingAndTrailingHTMLSpaces(value);
if (renderer() && isImageType()) {
setNeedsWidgetUpdate(true);
if (!m_imageLoader)
m_imageLoader = adoptPtr(new HTMLImageLoader(this));
m_imageLoader->updateFromElementIgnoringPreviousError();
} else {
reloadPluginOnAttributeChange(name);
}
} else if (name == classidAttr) {
m_classId = value;
reloadPluginOnAttributeChange(name);
} else {
HTMLPlugInElement::parseAttribute(name, value);
}
}
static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramValues)
{
int srcIndex = -1, dataIndex = -1;
for (unsigned i = 0; i < paramNames->size(); ++i) {
if (equalIgnoringCase((*paramNames)[i], "src"))
srcIndex = i;
else if (equalIgnoringCase((*paramNames)[i], "data"))
dataIndex = i;
}
if (srcIndex == -1 && dataIndex != -1) {
paramNames->append("src");
paramValues->append((*paramValues)[dataIndex]);
}
}
void HTMLObjectElement::parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues, String& url, String& serviceType)
{
HashSet<StringImpl*, CaseFoldingHash> uniqueParamNames;
String urlParameter;
for (HTMLParamElement* p = Traversal<HTMLParamElement>::firstChild(*this); p; p = Traversal<HTMLParamElement>::nextSibling(*p)) {
String name = p->name();
if (name.isEmpty())
continue;
uniqueParamNames.add(name.impl());
paramNames.append(p->name());
paramValues.append(p->value());
if (url.isEmpty() && urlParameter.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url")))
urlParameter = stripLeadingAndTrailingHTMLSpaces(p->value());
if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) {
serviceType = p->value();
size_t pos = serviceType.find(";");
if (pos != kNotFound)
serviceType = serviceType.left(pos);
}
}
String codebase;
if (MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) {
codebase = "codebase";
uniqueParamNames.add(codebase.impl());
}
if (hasAttributes()) {
unsigned attributeCount = this->attributeCount();
for (unsigned i = 0; i < attributeCount; ++i) {
const Attribute& attribute = attributeItem(i);
const AtomicString& name = attribute.name().localName();
if (!uniqueParamNames.contains(name.impl())) {
paramNames.append(name.string());
paramValues.append(attribute.value().string());
}
}
}
mapDataParamToSrc(¶mNames, ¶mValues);
if (url.isEmpty() && !urlParameter.isEmpty()) {
KURL completedURL = document().completeURL(urlParameter);
bool useFallback;
if (shouldUsePlugin(completedURL, serviceType, false, useFallback))
url = urlParameter;
}
}
bool HTMLObjectElement::hasFallbackContent() const
{
for (Node* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTextNode()) {
if (!toText(child)->containsOnlyWhitespace())
return true;
} else if (!isHTMLParamElement(*child)) {
return true;
}
}
return false;
}
bool HTMLObjectElement::shouldAllowQuickTimeClassIdQuirk()
{
if (!document().settings()
|| !document().settings()->needsSiteSpecificQuirks()
|| hasFallbackContent()
|| !equalIgnoringCase(classId(), "clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"))
return false;
RefPtr<HTMLCollection> metaElements = document().getElementsByTagName(HTMLNames::metaTag.localName());
unsigned length = metaElements->length();
for (unsigned i = 0; i < length; ++i) {
ASSERT(metaElements->item(i)->isHTMLElement());
HTMLMetaElement* metaElement = toHTMLMetaElement(metaElements->item(i));
if (equalIgnoringCase(metaElement->name(), "generator") && metaElement->content().startsWith("Mac OS X Server Web Services Server", false))
return true;
}
return false;
}
bool HTMLObjectElement::hasValidClassId()
{
if (MIMETypeRegistry::isJavaAppletMIMEType(m_serviceType) && classId().startsWith("java:", false))
return true;
if (shouldAllowQuickTimeClassIdQuirk())
return true;
return classId().isEmpty();
}
void HTMLObjectElement::reloadPluginOnAttributeChange(const QualifiedName& name)
{
bool needsInvalidation;
if (name == typeAttr) {
needsInvalidation = !fastHasAttribute(classidAttr) && !fastHasAttribute(dataAttr);
} else if (name == dataAttr) {
needsInvalidation = !fastHasAttribute(classidAttr);
} else if (name == classidAttr) {
needsInvalidation = true;
} else {
ASSERT_NOT_REACHED();
needsInvalidation = false;
}
setNeedsWidgetUpdate(true);
if (needsInvalidation)
setNeedsStyleRecalc(SubtreeStyleChange);
}
void HTMLObjectElement::updateWidgetInternal()
{
ASSERT(!renderEmbeddedObject()->showsUnavailablePluginIndicator());
ASSERT(needsWidgetUpdate());
setNeedsWidgetUpdate(false);
if (!isFinishedParsingChildren()) {
dispatchErrorEvent();
return;
}
if (!SubframeLoadingDisabler::canLoadFrame(*this)) {
dispatchErrorEvent();
return;
}
String url = this->url();
String serviceType = m_serviceType;
Vector<String> paramNames;
Vector<String> paramValues;
parametersForPlugin(paramNames, paramValues, url, serviceType);
if (!allowedToLoadFrameURL(url)) {
dispatchErrorEvent();
return;
}
bool fallbackContent = hasFallbackContent();
renderEmbeddedObject()->setHasFallbackContent(fallbackContent);
if (!renderer())
return;
if (!hasValidClassId() || !requestObject(url, serviceType, paramNames, paramValues)) {
if (!url.isEmpty())
dispatchErrorEvent();
if (fallbackContent)
renderFallbackContent();
}
}
bool HTMLObjectElement::rendererIsNeeded(const RenderStyle& style)
{
if (!document().frame())
return false;
return HTMLPlugInElement::rendererIsNeeded(style);
}
Node::InsertionNotificationRequest HTMLObjectElement::insertedInto(ContainerNode* insertionPoint)
{
HTMLPlugInElement::insertedInto(insertionPoint);
FormAssociatedElement::insertedInto(insertionPoint);
return InsertionDone;
}
void HTMLObjectElement::removedFrom(ContainerNode* insertionPoint)
{
HTMLPlugInElement::removedFrom(insertionPoint);
FormAssociatedElement::removedFrom(insertionPoint);
}
void HTMLObjectElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
{
if (inDocument() && !useFallbackContent()) {
setNeedsWidgetUpdate(true);
setNeedsStyleRecalc(SubtreeStyleChange);
}
HTMLPlugInElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
}
bool HTMLObjectElement::isURLAttribute(const Attribute& attribute) const
{
return attribute.name() == codebaseAttr || attribute.name() == dataAttr
|| (attribute.name() == usemapAttr && attribute.value().string()[0] != '#')
|| HTMLPlugInElement::isURLAttribute(attribute);
}
bool HTMLObjectElement::hasLegalLinkAttribute(const QualifiedName& name) const
{
return name == classidAttr || name == dataAttr || name == codebaseAttr || HTMLPlugInElement::hasLegalLinkAttribute(name);
}
const QualifiedName& HTMLObjectElement::subResourceAttributeName() const
{
return dataAttr;
}
const AtomicString HTMLObjectElement::imageSourceURL() const
{
return getAttribute(dataAttr);
}
void HTMLObjectElement::reattachFallbackContent()
{
if (document().inStyleRecalc())
reattach();
else
lazyReattachIfAttached();
}
void HTMLObjectElement::renderFallbackContent()
{
if (useFallbackContent())
return;
if (!inDocument())
return;
if (m_imageLoader && m_imageLoader->image() && m_imageLoader->image()->status() != Resource::LoadError) {
m_serviceType = m_imageLoader->image()->response().mimeType();
if (!isImageType()) {
m_imageLoader->setImage(0);
reattachFallbackContent();
return;
}
}
m_useFallbackContent = true;
reattachFallbackContent();
}
bool HTMLObjectElement::isExposed() const
{
for (HTMLObjectElement* ancestor = Traversal<HTMLObjectElement>::firstAncestor(*this); ancestor; ancestor = Traversal<HTMLObjectElement>::firstAncestor(*ancestor)) {
if (ancestor->isExposed())
return false;
}
for (HTMLElement* element = Traversal<HTMLElement>::firstWithin(*this); element; element = Traversal<HTMLElement>::next(*element, this)) {
if (isHTMLObjectElement(*element) || isHTMLEmbedElement(*element))
return false;
}
return true;
}
bool HTMLObjectElement::containsJavaApplet() const
{
if (MIMETypeRegistry::isJavaAppletMIMEType(getAttribute(typeAttr)))
return true;
for (HTMLElement* child = Traversal<HTMLElement>::firstChild(*this); child; child = Traversal<HTMLElement>::nextSibling(*child)) {
if (isHTMLParamElement(*child)
&& equalIgnoringCase(child->getNameAttribute(), "type")
&& MIMETypeRegistry::isJavaAppletMIMEType(child->getAttribute(valueAttr).string()))
return true;
if (isHTMLObjectElement(*child) && toHTMLObjectElement(*child).containsJavaApplet())
return true;
if (isHTMLAppletElement(*child))
return true;
}
return false;
}
void HTMLObjectElement::didMoveToNewDocument(Document& oldDocument)
{
FormAssociatedElement::didMoveToNewDocument(oldDocument);
HTMLPlugInElement::didMoveToNewDocument(oldDocument);
}
bool HTMLObjectElement::appendFormData(FormDataList& encoding, bool)
{
if (name().isEmpty())
return false;
Widget* widget = pluginWidget();
if (!widget || !widget->isPluginView())
return false;
String value;
if (!toPluginView(widget)->getFormValue(value))
return false;
encoding.appendData(name(), value);
return true;
}
HTMLFormElement* HTMLObjectElement::formOwner() const
{
return FormAssociatedElement::form();
}
bool HTMLObjectElement::isInteractiveContent() const
{
return fastHasAttribute(usemapAttr);
}
bool HTMLObjectElement::useFallbackContent() const
{
return HTMLPlugInElement::useFallbackContent() || m_useFallbackContent;
}
}