forked from mirrors/gecko-dev
Backed out changeset 5b1644096477 (bug 1682030) Backed out changeset 35ae60eea3c7 (bug 1682030) Backed out changeset 3eca76a6d639 (bug 1682030) Backed out changeset 259c45447ad9 (bug 1682030) Backed out changeset de9222dc8c31 (bug 1682030) Backed out changeset 2986c7e14349 (bug 1682030) Backed out changeset 6af3410bdb93 (bug 1682030) Backed out changeset 42b0621c2927 (bug 1682030) Backed out changeset 366e3e371858 (bug 1682030) Backed out changeset 9adb2865adea (bug 1682030) Backed out changeset 6af6af3bc03a (bug 1682030) Backed out changeset da94a91b35ae (bug 1682030) Backed out changeset 9143da258d0e (bug 1682030) Backed out changeset 5e20d06952ba (bug 1682030) Backed out changeset 6253d7e1ce7d (bug 1682030) Backed out changeset 0e06ddeea3e2 (bug 1682030) Backed out changeset 9c58d57c9e44 (bug 1682030) Backed out changeset e90edd89430e (bug 1682030) Backed out changeset 5861b8166b10 (bug 1682030) Backed out changeset b4b88cdc7993 (bug 1682030) Backed out changeset b80054e9805c (bug 1682030) Backed out changeset 580d857674c0 (bug 1682030) Backed out changeset a9cdf93c2662 (bug 1682030) Backed out changeset 9c9c8b4998e2 (bug 1682030)
330 lines
11 KiB
C++
330 lines
11 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/EventStates.h"
|
|
#include "mozilla/dom/BindContext.h"
|
|
#include "mozilla/dom/HTMLFormSubmission.h"
|
|
#include "mozilla/dom/HTMLObjectElement.h"
|
|
#include "mozilla/dom/HTMLObjectElementBinding.h"
|
|
#include "mozilla/dom/ElementInlines.h"
|
|
#include "mozilla/dom/WindowProxyHolder.h"
|
|
#include "nsAttrValueInlines.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "nsError.h"
|
|
#include "mozilla/dom/Document.h"
|
|
#include "nsIPluginDocument.h"
|
|
#include "nsNPAPIPluginInstance.h"
|
|
#include "nsIWidget.h"
|
|
#include "nsContentUtils.h"
|
|
#ifdef XP_MACOSX
|
|
# include "mozilla/EventDispatcher.h"
|
|
# include "mozilla/dom/Event.h"
|
|
# include "nsFocusManager.h"
|
|
#endif
|
|
|
|
namespace mozilla::dom {
|
|
|
|
HTMLObjectElement::HTMLObjectElement(
|
|
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
|
FromParser aFromParser)
|
|
: nsGenericHTMLFormElement(std::move(aNodeInfo), NS_FORM_OBJECT),
|
|
mIsDoneAddingChildren(!aFromParser) {
|
|
RegisterActivityObserver();
|
|
SetIsNetworkCreated(aFromParser == FROM_PARSER_NETWORK);
|
|
|
|
// <object> is always barred from constraint validation.
|
|
SetBarredFromConstraintValidation(true);
|
|
|
|
// By default we're in the loading state
|
|
AddStatesSilently(NS_EVENT_STATE_LOADING);
|
|
}
|
|
|
|
HTMLObjectElement::~HTMLObjectElement() {
|
|
UnregisterActivityObserver();
|
|
nsImageLoadingContent::Destroy();
|
|
}
|
|
|
|
bool HTMLObjectElement::IsInteractiveHTMLContent() const {
|
|
return HasAttr(kNameSpaceID_None, nsGkAtoms::usemap) ||
|
|
nsGenericHTMLFormElement::IsInteractiveHTMLContent();
|
|
}
|
|
|
|
void HTMLObjectElement::AsyncEventRunning(AsyncEventDispatcher* aEvent) {
|
|
nsImageLoadingContent::AsyncEventRunning(aEvent);
|
|
}
|
|
|
|
bool HTMLObjectElement::IsDoneAddingChildren() { return mIsDoneAddingChildren; }
|
|
|
|
void HTMLObjectElement::DoneAddingChildren(bool aHaveNotified) {
|
|
mIsDoneAddingChildren = true;
|
|
|
|
// If we're already in a document, we need to trigger the load
|
|
// Otherwise, BindToTree takes care of that.
|
|
if (IsInComposedDoc()) {
|
|
StartObjectLoad(aHaveNotified, false);
|
|
}
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLObjectElement)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLObjectElement,
|
|
nsGenericHTMLFormElement)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
|
|
nsObjectLoadingContent::Traverse(tmp, cb);
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLObjectElement,
|
|
nsGenericHTMLFormElement)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
|
|
nsObjectLoadingContent::Unlink(tmp);
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(
|
|
HTMLObjectElement, nsGenericHTMLFormElement, imgINotificationObserver,
|
|
nsIRequestObserver, nsIStreamListener, nsFrameLoaderOwner,
|
|
nsIObjectLoadingContent, nsIImageLoadingContent, nsIChannelEventSink,
|
|
nsIConstraintValidation)
|
|
|
|
NS_IMPL_ELEMENT_CLONE(HTMLObjectElement)
|
|
|
|
nsresult HTMLObjectElement::BindToTree(BindContext& aContext,
|
|
nsINode& aParent) {
|
|
nsresult rv = nsGenericHTMLFormElement::BindToTree(aContext, aParent);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = nsObjectLoadingContent::BindToTree(aContext, aParent);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Don't kick off load from being bound to a plugin document - the plugin
|
|
// document will call nsObjectLoadingContent::InitializeFromChannel() for the
|
|
// initial load.
|
|
if (IsInComposedDoc()) {
|
|
nsCOMPtr<nsIPluginDocument> pluginDoc =
|
|
do_QueryInterface(&aContext.OwnerDoc());
|
|
// If we already have all the children, start the load.
|
|
if (mIsDoneAddingChildren && !pluginDoc) {
|
|
void (HTMLObjectElement::*start)() = &HTMLObjectElement::StartObjectLoad;
|
|
nsContentUtils::AddScriptRunner(
|
|
NewRunnableMethod("dom::HTMLObjectElement::BindToTree", this, start));
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void HTMLObjectElement::UnbindFromTree(bool aNullParent) {
|
|
nsObjectLoadingContent::UnbindFromTree(aNullParent);
|
|
nsGenericHTMLFormElement::UnbindFromTree(aNullParent);
|
|
}
|
|
|
|
nsresult HTMLObjectElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
|
|
const nsAttrValue* aValue,
|
|
const nsAttrValue* aOldValue,
|
|
nsIPrincipal* aSubjectPrincipal,
|
|
bool aNotify) {
|
|
nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return nsGenericHTMLFormElement::AfterSetAttr(
|
|
aNamespaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify);
|
|
}
|
|
|
|
nsresult HTMLObjectElement::OnAttrSetButNotChanged(
|
|
int32_t aNamespaceID, nsAtom* aName, const nsAttrValueOrString& aValue,
|
|
bool aNotify) {
|
|
nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return nsGenericHTMLFormElement::OnAttrSetButNotChanged(aNamespaceID, aName,
|
|
aValue, aNotify);
|
|
}
|
|
|
|
nsresult HTMLObjectElement::AfterMaybeChangeAttr(int32_t aNamespaceID,
|
|
nsAtom* aName, bool aNotify) {
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
// if aNotify is false, we are coming from the parser or some such place;
|
|
// we'll get bound after all the attributes have been set, so we'll do the
|
|
// object load from BindToTree/DoneAddingChildren.
|
|
// Skip the LoadObject call in that case.
|
|
// We also don't want to start loading the object when we're not yet in
|
|
// a document, just in case that the caller wants to set additional
|
|
// attributes before inserting the node into the document.
|
|
if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren &&
|
|
aName == nsGkAtoms::data && !BlockEmbedOrObjectContentLoading()) {
|
|
return LoadObject(aNotify, true);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
bool HTMLObjectElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
|
|
int32_t* aTabIndex) {
|
|
// TODO: this should probably be managed directly by IsHTMLFocusable.
|
|
// See bug 597242.
|
|
Document* doc = GetComposedDoc();
|
|
if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
|
|
if (aTabIndex) {
|
|
*aTabIndex = -1;
|
|
}
|
|
|
|
*aIsFocusable = false;
|
|
return false;
|
|
}
|
|
|
|
// If we have decided that this is a blocked plugin then do not allow focus.
|
|
if ((Type() == eType_Null) &&
|
|
(PluginFallbackType() == eFallbackBlockAllPlugins)) {
|
|
if (aTabIndex) {
|
|
*aTabIndex = -1;
|
|
}
|
|
|
|
*aIsFocusable = false;
|
|
return false;
|
|
}
|
|
|
|
const nsAttrValue* attrVal = mAttrs.GetAttr(nsGkAtoms::tabindex);
|
|
bool isFocusable = attrVal && attrVal->Type() == nsAttrValue::eInteger;
|
|
|
|
// This method doesn't call nsGenericHTMLFormElement intentionally.
|
|
// TODO: It should probably be changed when bug 597242 will be fixed.
|
|
if (IsEditableRoot() ||
|
|
((Type() == eType_Document || Type() == eType_FakePlugin) &&
|
|
nsContentUtils::IsSubDocumentTabbable(this))) {
|
|
if (aTabIndex) {
|
|
*aTabIndex = isFocusable ? attrVal->GetIntegerValue() : 0;
|
|
}
|
|
|
|
*aIsFocusable = true;
|
|
return false;
|
|
}
|
|
|
|
// TODO: this should probably be managed directly by IsHTMLFocusable.
|
|
// See bug 597242.
|
|
if (aTabIndex && isFocusable) {
|
|
*aTabIndex = attrVal->GetIntegerValue();
|
|
*aIsFocusable = true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
HTMLObjectElement::Reset() { return NS_OK; }
|
|
|
|
NS_IMETHODIMP
|
|
HTMLObjectElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission) {
|
|
return NS_OK;
|
|
}
|
|
|
|
int32_t HTMLObjectElement::TabIndexDefault() { return 0; }
|
|
|
|
Nullable<WindowProxyHolder> HTMLObjectElement::GetContentWindow(
|
|
nsIPrincipal& aSubjectPrincipal) {
|
|
Document* doc = GetContentDocument(aSubjectPrincipal);
|
|
if (doc) {
|
|
nsPIDOMWindowOuter* win = doc->GetWindow();
|
|
if (win) {
|
|
return WindowProxyHolder(win->GetBrowsingContext());
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool HTMLObjectElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
|
|
const nsAString& aValue,
|
|
nsIPrincipal* aMaybeScriptedPrincipal,
|
|
nsAttrValue& aResult) {
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
if (aAttribute == nsGkAtoms::align) {
|
|
return ParseAlignValue(aValue, aResult);
|
|
}
|
|
if (ParseImageAttribute(aAttribute, aValue, aResult)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return nsGenericHTMLFormElement::ParseAttribute(
|
|
aNamespaceID, aAttribute, aValue, aMaybeScriptedPrincipal, aResult);
|
|
}
|
|
|
|
void HTMLObjectElement::MapAttributesIntoRule(
|
|
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
|
|
nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aDecls);
|
|
nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aDecls);
|
|
nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aDecls);
|
|
nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aDecls);
|
|
nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aDecls);
|
|
}
|
|
|
|
NS_IMETHODIMP_(bool)
|
|
HTMLObjectElement::IsAttributeMapped(const nsAtom* aAttribute) const {
|
|
static const MappedAttributeEntry* const map[] = {
|
|
sCommonAttributeMap,
|
|
sImageMarginSizeAttributeMap,
|
|
sImageBorderAttributeMap,
|
|
sImageAlignAttributeMap,
|
|
};
|
|
|
|
return FindAttributeDependence(aAttribute, map);
|
|
}
|
|
|
|
nsMapRuleToAttributesFunc HTMLObjectElement::GetAttributeMappingFunction()
|
|
const {
|
|
return &MapAttributesIntoRule;
|
|
}
|
|
|
|
void HTMLObjectElement::StartObjectLoad(bool aNotify, bool aForce) {
|
|
// BindToTree can call us asynchronously, and we may be removed from the tree
|
|
// in the interim
|
|
if (!IsInComposedDoc() || !OwnerDoc()->IsActive() ||
|
|
BlockEmbedOrObjectContentLoading()) {
|
|
return;
|
|
}
|
|
|
|
LoadObject(aNotify, aForce);
|
|
SetIsNetworkCreated(false);
|
|
}
|
|
|
|
EventStates HTMLObjectElement::IntrinsicState() const {
|
|
return nsGenericHTMLFormElement::IntrinsicState() | ObjectState();
|
|
}
|
|
|
|
uint32_t HTMLObjectElement::GetCapabilities() const {
|
|
return nsObjectLoadingContent::GetCapabilities() | eFallbackIfClassIDPresent;
|
|
}
|
|
|
|
void HTMLObjectElement::DestroyContent() {
|
|
nsObjectLoadingContent::Destroy();
|
|
nsGenericHTMLFormElement::DestroyContent();
|
|
}
|
|
|
|
nsresult HTMLObjectElement::CopyInnerTo(Element* aDest) {
|
|
nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (aDest->OwnerDoc()->IsStaticDocument()) {
|
|
CreateStaticClone(static_cast<HTMLObjectElement*>(aDest));
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
JSObject* HTMLObjectElement::WrapNode(JSContext* aCx,
|
|
JS::Handle<JSObject*> aGivenProto) {
|
|
JS::Rooted<JSObject*> obj(
|
|
aCx, HTMLObjectElement_Binding::Wrap(aCx, this, aGivenProto));
|
|
if (!obj) {
|
|
return nullptr;
|
|
}
|
|
SetupProtoChain(aCx, obj);
|
|
return obj;
|
|
}
|
|
|
|
} // namespace mozilla::dom
|
|
|
|
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Object)
|