blob: f27a8299ba80cae26e3ab919c37614e3fe997f3b [file] [log] [blame]
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Stefan Schimanski (1Stein@gmx.de)
* Copyright (C) 2004, 2005, 2006, 2008, 2009, 2011 Apple Inc. All rights
* reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "third_party/blink/renderer/core/html/html_embed_element.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/html/html_image_loader.h"
#include "third_party/blink/renderer/core/html/html_object_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/plugin_document.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_object.h"
namespace blink {
HTMLEmbedElement::HTMLEmbedElement(Document& document,
const CreateElementFlags flags)
: HTMLPlugInElement(html_names::kEmbedTag,
document,
flags,
kShouldPreferPlugInsForImages) {
EnsureUserAgentShadowRoot();
}
const AttrNameToTrustedType& HTMLEmbedElement::GetCheckedAttributeTypes()
const {
DEFINE_STATIC_LOCAL(AttrNameToTrustedType, attribute_map,
({{"src", SpecificTrustedType::kTrustedScriptURL}}));
return attribute_map;
}
static inline LayoutEmbeddedContent* FindPartLayoutObject(const Node* n) {
if (!n->GetLayoutObject())
n = Traversal<HTMLObjectElement>::FirstAncestor(*n);
if (n && n->GetLayoutObject() &&
n->GetLayoutObject()->IsLayoutEmbeddedContent())
return ToLayoutEmbeddedContent(n->GetLayoutObject());
return nullptr;
}
LayoutEmbeddedContent* HTMLEmbedElement::ExistingLayoutEmbeddedContent() const {
return FindPartLayoutObject(this);
}
bool HTMLEmbedElement::IsPresentationAttribute(
const QualifiedName& name) const {
if (name == html_names::kHiddenAttr)
return true;
return HTMLPlugInElement::IsPresentationAttribute(name);
}
void HTMLEmbedElement::CollectStyleForPresentationAttribute(
const QualifiedName& name,
const AtomicString& value,
MutableCSSPropertyValueSet* style) {
if (name == html_names::kHiddenAttr) {
if (DeprecatedEqualIgnoringCase(value, "yes") ||
EqualIgnoringASCIICase(value, "true")) {
AddPropertyToPresentationAttributeStyle(
style, CSSPropertyID::kWidth, 0,
CSSPrimitiveValue::UnitType::kPixels);
AddPropertyToPresentationAttributeStyle(
style, CSSPropertyID::kHeight, 0,
CSSPrimitiveValue::UnitType::kPixels);
}
} else {
HTMLPlugInElement::CollectStyleForPresentationAttribute(name, value, style);
}
}
void HTMLEmbedElement::ParseAttribute(
const AttributeModificationParams& params) {
if (params.name == html_names::kTypeAttr) {
SetServiceType(params.new_value.LowerASCII());
wtf_size_t pos = service_type_.Find(";");
if (pos != kNotFound)
SetServiceType(service_type_.Left(pos));
if (GetLayoutObject()) {
SetNeedsPluginUpdate(true);
SetDisposeView();
GetLayoutObject()->SetNeedsLayoutAndFullPaintInvalidation(
"Embed type changed");
}
} else if (params.name == html_names::kCodeAttr) {
// TODO(schenney): Remove this branch? It's not in the spec and we're not in
// the HTMLAppletElement hierarchy.
SetUrl(StripLeadingAndTrailingHTMLSpaces(params.new_value));
SetDisposeView();
} else if (params.name == html_names::kSrcAttr) {
SetUrl(StripLeadingAndTrailingHTMLSpaces(params.new_value));
if (GetLayoutObject() && IsImageType()) {
SetDisposeView();
if (!image_loader_)
image_loader_ = MakeGarbageCollected<HTMLImageLoader>(this);
image_loader_->UpdateFromElement(ImageLoader::kUpdateIgnorePreviousError);
} else if (GetLayoutObject()) {
// Check if this Embed can transition from potentially-active to active
if (FastHasAttribute(html_names::kTypeAttr)) {
SetNeedsPluginUpdate(true);
ReattachOnPluginChangeIfNeeded();
}
}
} else {
HTMLPlugInElement::ParseAttribute(params);
}
}
void HTMLEmbedElement::ParametersForPlugin(PluginParameters& plugin_params) {
AttributeCollection attributes = Attributes();
for (const Attribute& attribute : attributes)
plugin_params.AppendAttribute(attribute);
}
// FIXME: This should be unified with HTMLObjectElement::UpdatePlugin and
// moved down into html_plugin_element.cc
void HTMLEmbedElement::UpdatePluginInternal() {
DCHECK(!GetLayoutEmbeddedObject()->ShowsUnavailablePluginIndicator());
DCHECK(NeedsPluginUpdate());
SetNeedsPluginUpdate(false);
if (url_.IsEmpty() && service_type_.IsEmpty())
return;
// Note these pass url_ and service_type_ to allow better code sharing with
// <object> which modifies url and serviceType before calling these.
if (!AllowedToLoadFrameURL(url_))
return;
PluginParameters plugin_params;
ParametersForPlugin(plugin_params);
// FIXME: Can we not have GetLayoutObject() here now that beforeload events
// are gone?
if (!GetLayoutObject())
return;
// Overwrites the URL and MIME type of a Flash embed to use an HTML5 embed.
KURL overriden_url =
GetDocument().GetFrame()->Client()->OverrideFlashEmbedWithHTML(
GetDocument().CompleteURL(url_));
if (!overriden_url.IsEmpty()) {
url_ = overriden_url.GetString();
SetServiceType("text/html");
}
RequestObject(plugin_params);
}
bool HTMLEmbedElement::LayoutObjectIsNeeded(const ComputedStyle& style) const {
if (IsImageType())
return HTMLPlugInElement::LayoutObjectIsNeeded(style);
// https://html.spec.whatwg.org/C/#the-embed-element
// While any of the following conditions are occurring, any plugin
// instantiated for the element must be removed, and the embed element
// represents nothing:
// * The element has neither a src attribute nor a type attribute.
if (!FastHasAttribute(html_names::kSrcAttr) &&
!FastHasAttribute(html_names::kTypeAttr))
return false;
// * The element has a media element ancestor.
// -> It's realized by LayoutMedia::isChildAllowed.
// * The element has an ancestor object element that is not showing its
// fallback content.
ContainerNode* p = parentNode();
if (auto* object = DynamicTo<HTMLObjectElement>(p)) {
if (!object->WillUseFallbackContentAtLayout() &&
!object->UseFallbackContent()) {
return false;
}
}
return HTMLPlugInElement::LayoutObjectIsNeeded(style);
}
bool HTMLEmbedElement::IsURLAttribute(const Attribute& attribute) const {
return attribute.GetName() == html_names::kSrcAttr ||
HTMLPlugInElement::IsURLAttribute(attribute);
}
const QualifiedName& HTMLEmbedElement::SubResourceAttributeName() const {
return html_names::kSrcAttr;
}
bool HTMLEmbedElement::IsInteractiveContent() const {
return true;
}
bool HTMLEmbedElement::IsExposed() const {
// http://www.whatwg.org/specs/web-apps/current-work/#exposed
for (HTMLObjectElement* object =
Traversal<HTMLObjectElement>::FirstAncestor(*this);
object; object = Traversal<HTMLObjectElement>::FirstAncestor(*object)) {
if (object->IsExposed())
return false;
}
return true;
}
} // namespace blink