tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HTMLObjectElement.cpp (9519B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/dom/HTMLObjectElement.h"
      8 
      9 #include "mozilla/dom/BindContext.h"
     10 #include "mozilla/dom/Document.h"
     11 #include "mozilla/dom/ElementInlines.h"
     12 #include "mozilla/dom/HTMLObjectElementBinding.h"
     13 #include "mozilla/dom/WindowProxyHolder.h"
     14 #include "nsAttrValueInlines.h"
     15 #include "nsContentUtils.h"
     16 #include "nsError.h"
     17 #include "nsGkAtoms.h"
     18 #include "nsIContentInlines.h"
     19 #include "nsIWidget.h"
     20 #ifdef XP_MACOSX
     21 #  include "mozilla/EventDispatcher.h"
     22 #  include "mozilla/dom/Event.h"
     23 #  include "nsFocusManager.h"
     24 #endif
     25 
     26 namespace mozilla::dom {
     27 
     28 HTMLObjectElement::HTMLObjectElement(
     29    already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
     30    FromParser aFromParser)
     31    : nsGenericHTMLFormControlElement(std::move(aNodeInfo),
     32                                      FormControlType::Object),
     33      mIsDoneAddingChildren(!aFromParser) {
     34  SetIsNetworkCreated(aFromParser == FROM_PARSER_NETWORK);
     35 
     36  // <object> is always barred from constraint validation.
     37  SetBarredFromConstraintValidation(true);
     38 }
     39 
     40 HTMLObjectElement::~HTMLObjectElement() = default;
     41 
     42 bool HTMLObjectElement::IsInteractiveHTMLContent() const {
     43  return HasAttr(nsGkAtoms::usemap) ||
     44         nsGenericHTMLFormControlElement::IsInteractiveHTMLContent();
     45 }
     46 
     47 void HTMLObjectElement::DoneAddingChildren(bool aHaveNotified) {
     48  mIsDoneAddingChildren = true;
     49 
     50  // If we're already in a document, we need to trigger the load
     51  // Otherwise, BindToTree takes care of that.
     52  if (IsInComposedDoc()) {
     53    StartObjectLoad(aHaveNotified, false);
     54  }
     55 }
     56 
     57 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLObjectElement)
     58 
     59 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
     60    HTMLObjectElement, nsGenericHTMLFormControlElement)
     61  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
     62  nsObjectLoadingContent::Traverse(tmp, cb);
     63 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     64 
     65 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLObjectElement,
     66                                                nsGenericHTMLFormControlElement)
     67  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
     68  nsObjectLoadingContent::Unlink(tmp);
     69 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     70 
     71 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(
     72    HTMLObjectElement, nsGenericHTMLFormControlElement, nsIRequestObserver,
     73    nsIStreamListener, nsFrameLoaderOwner, nsIObjectLoadingContent,
     74    nsIChannelEventSink, nsIConstraintValidation)
     75 
     76 NS_IMPL_ELEMENT_CLONE(HTMLObjectElement)
     77 
     78 nsresult HTMLObjectElement::BindToTree(BindContext& aContext,
     79                                       nsINode& aParent) {
     80  nsresult rv = nsGenericHTMLFormControlElement::BindToTree(aContext, aParent);
     81  NS_ENSURE_SUCCESS(rv, rv);
     82 
     83  // If we already have all the children, start the load.
     84  if (IsInComposedDoc() && mIsDoneAddingChildren) {
     85    void (HTMLObjectElement::*start)() = &HTMLObjectElement::StartObjectLoad;
     86    nsContentUtils::AddScriptRunner(
     87        NewRunnableMethod("dom::HTMLObjectElement::BindToTree", this, start));
     88  }
     89 
     90  return NS_OK;
     91 }
     92 
     93 void HTMLObjectElement::UnbindFromTree(UnbindContext& aContext) {
     94  nsObjectLoadingContent::UnbindFromTree();
     95  nsGenericHTMLFormControlElement::UnbindFromTree(aContext);
     96 }
     97 
     98 void HTMLObjectElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
     99                                     const nsAttrValue* aValue,
    100                                     const nsAttrValue* aOldValue,
    101                                     nsIPrincipal* aSubjectPrincipal,
    102                                     bool aNotify) {
    103  AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
    104 
    105  if (aName == nsGkAtoms::data) {
    106    RefreshFeaturePolicy();
    107  }
    108 
    109  return nsGenericHTMLFormControlElement::AfterSetAttr(
    110      aNamespaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify);
    111 }
    112 
    113 void HTMLObjectElement::OnAttrSetButNotChanged(
    114    int32_t aNamespaceID, nsAtom* aName, const nsAttrValueOrString& aValue,
    115    bool aNotify) {
    116  AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
    117  return nsGenericHTMLFormControlElement::OnAttrSetButNotChanged(
    118      aNamespaceID, aName, aValue, aNotify);
    119 }
    120 
    121 void HTMLObjectElement::AfterMaybeChangeAttr(int32_t aNamespaceID,
    122                                             nsAtom* aName, bool aNotify) {
    123  // if aNotify is false, we are coming from the parser or some such place;
    124  // we'll get bound after all the attributes have been set, so we'll do the
    125  // object load from BindToTree/DoneAddingChildren.
    126  // Skip the LoadObject call in that case.
    127  // We also don't want to start loading the object when we're not yet in
    128  // a document, just in case that the caller wants to set additional
    129  // attributes before inserting the node into the document.
    130  if (aNamespaceID != kNameSpaceID_None || aName != nsGkAtoms::data ||
    131      !aNotify || !IsInComposedDoc() || !mIsDoneAddingChildren ||
    132      BlockEmbedOrObjectContentLoading()) {
    133    return;
    134  }
    135 
    136  nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
    137      "HTMLObjectElement::LoadObject",
    138      [self = RefPtr<HTMLObjectElement>(this), aNotify]() {
    139        if (self->IsInComposedDoc()) {
    140          self->LoadObject(aNotify, true);
    141        }
    142      }));
    143 }
    144 
    145 bool HTMLObjectElement::IsHTMLFocusable(IsFocusableFlags aFlags,
    146                                        bool* aIsFocusable,
    147                                        int32_t* aTabIndex) {
    148  // TODO: this should probably be managed directly by IsHTMLFocusable.
    149  // See bug 597242.
    150  Document* doc = GetComposedDoc();
    151  if (!doc || IsInDesignMode()) {
    152    if (aTabIndex) {
    153      *aTabIndex = -1;
    154    }
    155 
    156    *aIsFocusable = false;
    157    return false;
    158  }
    159 
    160  const nsAttrValue* attrVal = mAttrs.GetAttr(nsGkAtoms::tabindex);
    161  bool isFocusable = attrVal && attrVal->Type() == nsAttrValue::eInteger;
    162 
    163  // This method doesn't call nsGenericHTMLFormControlElement intentionally.
    164  // TODO: It should probably be changed when bug 597242 will be fixed.
    165  if (IsEditingHost() || Type() == ObjectType::Document) {
    166    if (aTabIndex) {
    167      *aTabIndex = isFocusable ? attrVal->GetIntegerValue() : 0;
    168    }
    169 
    170    *aIsFocusable = true;
    171    return false;
    172  }
    173 
    174  // TODO: this should probably be managed directly by IsHTMLFocusable.
    175  // See bug 597242.
    176  if (aTabIndex && isFocusable) {
    177    *aTabIndex = attrVal->GetIntegerValue();
    178    *aIsFocusable = true;
    179  }
    180 
    181  return false;
    182 }
    183 
    184 int32_t HTMLObjectElement::TabIndexDefault() { return 0; }
    185 
    186 Nullable<WindowProxyHolder> HTMLObjectElement::GetContentWindow(
    187    nsIPrincipal& aSubjectPrincipal) {
    188  Document* doc = GetContentDocument(aSubjectPrincipal);
    189  if (doc) {
    190    nsPIDOMWindowOuter* win = doc->GetWindow();
    191    if (win) {
    192      return WindowProxyHolder(win->GetBrowsingContext());
    193    }
    194  }
    195 
    196  return nullptr;
    197 }
    198 
    199 bool HTMLObjectElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
    200                                       const nsAString& aValue,
    201                                       nsIPrincipal* aMaybeScriptedPrincipal,
    202                                       nsAttrValue& aResult) {
    203  if (aNamespaceID == kNameSpaceID_None) {
    204    if (aAttribute == nsGkAtoms::align) {
    205      return ParseAlignValue(aValue, aResult);
    206    }
    207    if (ParseImageAttribute(aAttribute, aValue, aResult)) {
    208      return true;
    209    }
    210  }
    211 
    212  return nsGenericHTMLFormControlElement::ParseAttribute(
    213      aNamespaceID, aAttribute, aValue, aMaybeScriptedPrincipal, aResult);
    214 }
    215 
    216 void HTMLObjectElement::MapAttributesIntoRule(
    217    MappedDeclarationsBuilder& aBuilder) {
    218  MapImageAlignAttributeInto(aBuilder);
    219  MapImageBorderAttributeInto(aBuilder);
    220  MapImageMarginAttributeInto(aBuilder);
    221  MapImageSizeAttributesInto(aBuilder);
    222  MapCommonAttributesInto(aBuilder);
    223 }
    224 
    225 NS_IMETHODIMP_(bool)
    226 HTMLObjectElement::IsAttributeMapped(const nsAtom* aAttribute) const {
    227  static const MappedAttributeEntry* const map[] = {
    228      sCommonAttributeMap,
    229      sImageMarginSizeAttributeMap,
    230      sImageBorderAttributeMap,
    231      sImageAlignAttributeMap,
    232  };
    233 
    234  return FindAttributeDependence(aAttribute, map);
    235 }
    236 
    237 nsMapRuleToAttributesFunc HTMLObjectElement::GetAttributeMappingFunction()
    238    const {
    239  return &MapAttributesIntoRule;
    240 }
    241 
    242 void HTMLObjectElement::StartObjectLoad(bool aNotify, bool aForce) {
    243  // BindToTree can call us asynchronously, and we may be removed from the tree
    244  // in the interim
    245  if (!IsInComposedDoc() || !OwnerDoc()->IsActive() ||
    246      BlockEmbedOrObjectContentLoading()) {
    247    return;
    248  }
    249 
    250  LoadObject(aNotify, aForce);
    251  SetIsNetworkCreated(false);
    252 }
    253 
    254 uint32_t HTMLObjectElement::GetCapabilities() const {
    255  return nsObjectLoadingContent::GetCapabilities() | eFallbackIfClassIDPresent;
    256 }
    257 
    258 void HTMLObjectElement::DestroyContent() {
    259  nsObjectLoadingContent::Destroy();
    260  nsGenericHTMLFormControlElement::DestroyContent();
    261 }
    262 
    263 nsresult HTMLObjectElement::CopyInnerTo(Element* aDest) {
    264  nsresult rv = nsGenericHTMLFormControlElement::CopyInnerTo(aDest);
    265  NS_ENSURE_SUCCESS(rv, rv);
    266 
    267  if (aDest->OwnerDoc()->IsStaticDocument()) {
    268    CreateStaticClone(static_cast<HTMLObjectElement*>(aDest));
    269  }
    270 
    271  return rv;
    272 }
    273 
    274 JSObject* HTMLObjectElement::WrapNode(JSContext* aCx,
    275                                      JS::Handle<JSObject*> aGivenProto) {
    276  return HTMLObjectElement_Binding::Wrap(aCx, this, aGivenProto);
    277 }
    278 
    279 }  // namespace mozilla::dom
    280 
    281 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Object)