Files
tubestation/dom/html/HTMLIFrameElement.cpp
Kirk Steuber e2ea33731f Bug 1363481 - Add the old attribute value as a parameter to Element::AfterSetAttr r=bz
In order to facilitate the movement of code with side-effects called by Element::SetAttr to Element::BeforeSetAttr and Element::AfterSetAttr, Element::AfterSetAttr should have access to the old value of the attribute. This includes information about whether there was previously a value set or not.

Accomplishing this involved passing an additional argument through functions that find and change the old attribute value in order to ensure that we can differentiate between an empty old value and an absent old value (attribute was not set).

Note that while I tried to ensure that accurate values (and their absence) are reported to Element::AfterSetAttr, I largely ignored SVG. While the old value reported for SVG values should be however accurate the value already being reported to SetAttrAndNotify was, SVG elements do not currently report unset values properly because they will never pass a null pointer to SetAttrAndNotify.

MozReview-Commit-ID: K1mha8CNFZP
2017-05-18 14:09:01 -07:00

226 lines
7.3 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/HTMLIFrameElement.h"
#include "mozilla/dom/HTMLIFrameElementBinding.h"
#include "mozilla/GenericSpecifiedValuesInlines.h"
#include "nsMappedAttributes.h"
#include "nsAttrValueInlines.h"
#include "nsError.h"
#include "nsStyleConsts.h"
#include "nsContentUtils.h"
#include "nsSandboxFlags.h"
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame)
namespace mozilla {
namespace dom {
// static
const DOMTokenListSupportedToken HTMLIFrameElement::sSupportedSandboxTokens[] = {
#define SANDBOX_KEYWORD(string, atom, flags) string,
#include "IframeSandboxKeywordList.h"
#undef SANDBOX_KEYWORD
nullptr
};
HTMLIFrameElement::HTMLIFrameElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
FromParser aFromParser)
: nsGenericHTMLFrameElement(aNodeInfo, aFromParser)
{
}
HTMLIFrameElement::~HTMLIFrameElement()
{
}
NS_IMPL_ISUPPORTS_INHERITED(HTMLIFrameElement, nsGenericHTMLFrameElement,
nsIDOMHTMLIFrameElement)
NS_IMPL_ELEMENT_CLONE(HTMLIFrameElement)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Align, align)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, FrameBorder, frameborder)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Height, height)
NS_IMPL_URI_ATTR(HTMLIFrameElement, LongDesc, longdesc)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, MarginHeight, marginheight)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, MarginWidth, marginwidth)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Name, name)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Scrolling, scrolling)
NS_IMPL_URI_ATTR(HTMLIFrameElement, Src, src)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Width, width)
NS_IMPL_BOOL_ATTR(HTMLIFrameElement, AllowFullscreen, allowfullscreen)
NS_IMPL_STRING_ATTR(HTMLIFrameElement, Srcdoc, srcdoc)
NS_IMETHODIMP
HTMLIFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
{
return nsGenericHTMLFrameElement::GetContentDocument(aContentDocument);
}
bool
HTMLIFrameElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::marginwidth) {
return aResult.ParseSpecialIntValue(aValue);
}
if (aAttribute == nsGkAtoms::marginheight) {
return aResult.ParseSpecialIntValue(aValue);
}
if (aAttribute == nsGkAtoms::width) {
return aResult.ParseSpecialIntValue(aValue);
}
if (aAttribute == nsGkAtoms::height) {
return aResult.ParseSpecialIntValue(aValue);
}
if (aAttribute == nsGkAtoms::frameborder) {
return ParseFrameborderValue(aValue, aResult);
}
if (aAttribute == nsGkAtoms::scrolling) {
return ParseScrollingValue(aValue, aResult);
}
if (aAttribute == nsGkAtoms::align) {
return ParseAlignValue(aValue, aResult);
}
if (aAttribute == nsGkAtoms::sandbox) {
aResult.ParseAtomArray(aValue);
return true;
}
}
return nsGenericHTMLFrameElement::ParseAttribute(aNamespaceID, aAttribute,
aValue, aResult);
}
void
HTMLIFrameElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
GenericSpecifiedValues* aData)
{
if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Border))) {
// frameborder: 0 | 1 (| NO | YES in quirks mode)
// If frameborder is 0 or No, set border to 0
// else leave it as the value set in html.css
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::frameborder);
if (value && value->Type() == nsAttrValue::eEnum) {
int32_t frameborder = value->GetEnumValue();
if (NS_STYLE_FRAME_0 == frameborder ||
NS_STYLE_FRAME_NO == frameborder ||
NS_STYLE_FRAME_OFF == frameborder) {
aData->SetPixelValueIfUnset(eCSSProperty_border_top_width, 0.0f);
aData->SetPixelValueIfUnset(eCSSProperty_border_right_width, 0.0f);
aData->SetPixelValueIfUnset(eCSSProperty_border_bottom_width, 0.0f);
aData->SetPixelValueIfUnset(eCSSProperty_border_left_width, 0.0f);
}
}
}
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
}
NS_IMETHODIMP_(bool)
HTMLIFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
static const MappedAttributeEntry attributes[] = {
{ &nsGkAtoms::width },
{ &nsGkAtoms::height },
{ &nsGkAtoms::frameborder },
{ nullptr },
};
static const MappedAttributeEntry* const map[] = {
attributes,
sImageAlignAttributeMap,
sCommonAttributeMap,
};
return FindAttributeDependence(aAttribute, map);
}
nsMapRuleToAttributesFunc
HTMLIFrameElement::GetAttributeMappingFunction() const
{
return &MapAttributesIntoRule;
}
nsresult
HTMLIFrameElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
bool aNotify)
{
nsresult rv = nsGenericHTMLFrameElement::SetAttr(aNameSpaceID, aName,
aPrefix, aValue, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::srcdoc) {
// Don't propagate error here. The attribute was successfully set, that's
// what we should reflect.
LoadSrc();
}
return NS_OK;
}
nsresult
HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
const nsAttrValue* aOldValue, bool aNotify)
{
if (aName == nsGkAtoms::sandbox &&
aNameSpaceID == kNameSpaceID_None && mFrameLoader) {
// If we have an nsFrameLoader, apply the new sandbox flags.
// Since this is called after the setter, the sandbox flags have
// alreay been updated.
mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
}
return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aOldValue, aNotify);
}
nsresult
HTMLIFrameElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
bool aNotify)
{
// Invoke on the superclass.
nsresult rv = nsGenericHTMLFrameElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (aNameSpaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::srcdoc) {
// Fall back to the src attribute, if any
LoadSrc();
}
return NS_OK;
}
uint32_t
HTMLIFrameElement::GetSandboxFlags()
{
const nsAttrValue* sandboxAttr = GetParsedAttr(nsGkAtoms::sandbox);
// No sandbox attribute, no sandbox flags.
if (!sandboxAttr) {
return SANDBOXED_NONE;
}
return nsContentUtils::ParseSandboxAttributeToFlags(sandboxAttr);
}
JSObject*
HTMLIFrameElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return HTMLIFrameElementBinding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla