Esempio n. 1
0
void
HTMLImageElement::PictureSourceSizesChanged(nsIContent *aSourceNode,
                                            const nsAString& aNewValue,
                                            bool aNotify)
{
  if (!HTMLPictureElement::IsPictureEnabled()) {
    return;
  }

  MOZ_ASSERT(aSourceNode == this ||
             IsPreviousSibling(aSourceNode, this),
             "Should not be getting notifications for non-previous-siblings");

  nsIContent *currentSrc =
    mResponsiveSelector ? mResponsiveSelector->Content() : nullptr;

  if (aSourceNode == currentSrc) {
    // We're currently using this node as our responsive selector
    // source.
    mResponsiveSelector->SetSizesFromDescriptor(aNewValue);
  }

  // This always triggers the image update steps per the spec, even if
  // we are not using this source.
  QueueImageLoadTask(true);
}
Esempio n. 2
0
void
HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
{
  if (mForm) {
    if (aNullParent || !FindAncestorForm(mForm)) {
      ClearForm(true);
    } else {
      UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
    }
  }

  if (mInDocResponsiveContent) {
    nsIDocument* doc = GetOurOwnerDoc();
    MOZ_ASSERT(doc);
    if (doc) {
      doc->RemoveResponsiveContent(this);
      mInDocResponsiveContent = false;
    }
  }

  if (GetParent() &&
      GetParent()->IsHTMLElement(nsGkAtoms::picture) &&
      HTMLPictureElement::IsPictureEnabled()) {
    // Being removed from picture re-triggers selection, even if we
    // weren't using a <source> peer
    if (aNullParent) {
      QueueImageLoadTask(true);
    }
  }

  nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
  nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
Esempio n. 3
0
void
HTMLImageElement::PictureSourceRemoved(nsIContent *aSourceNode)
{
  if (!HTMLPictureElement::IsPictureEnabled()) {
    return;
  }

  QueueImageLoadTask(true);
}
Esempio n. 4
0
nsresult
HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                             nsIContent* aBindingParent,
                             bool aCompileEventHandlers)
{
  nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                 aBindingParent,
                                                 aCompileEventHandlers);
  NS_ENSURE_SUCCESS(rv, rv);

  nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
                                    aCompileEventHandlers);

  if (aParent) {
    UpdateFormOwner();
  }

  if (HaveSrcsetOrInPicture()) {
    if (aDocument && !mInDocResponsiveContent) {
      aDocument->AddResponsiveContent(this);
      mInDocResponsiveContent = true;
    }

    bool forceLoadEvent = HTMLPictureElement::IsPictureEnabled() &&
      aParent && aParent->IsHTMLElement(nsGkAtoms::picture);
    QueueImageLoadTask(forceLoadEvent);
  } else if (!InResponsiveMode() &&
             HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
    // We skip loading when our attributes were set from parser land,
    // so trigger a aForce=false load now to check if things changed.
    // This isn't necessary for responsive mode, since creating the
    // image load task is asynchronous we don't need to take special
    // care to avoid doing so when being filled by the parser.

    // FIXME: Bug 660963 it would be nice if we could just have
    // ClearBrokenState update our state and do it fast...
    ClearBrokenState();
    RemoveStatesSilently(NS_EVENT_STATE_BROKEN);

    // We still act synchronously for the non-responsive case (Bug
    // 1076583), but still need to delay if it is unsafe to run
    // script.

    // If loading is temporarily disabled, don't even launch MaybeLoadImage.
    // Otherwise MaybeLoadImage may run later when someone has reenabled
    // loading.
    if (LoadingEnabled()) {
      nsContentUtils::AddScriptRunner(
          NS_NewRunnableMethod(this, &HTMLImageElement::MaybeLoadImage));
    }
  }

  return rv;
}
Esempio n. 5
0
nsresult
HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                          nsIAtom* aPrefix, const nsAString& aValue,
                          bool aNotify)
{
  // We need to force our image to reload.  This must be done here, not in
  // AfterSetAttr or BeforeSetAttr, because we want to do it even if the attr is
  // being set to its existing value, which is normally optimized away as a
  // no-op.
  //
  // If we are in responsive mode, we drop the forced reload behavior,
  // but still trigger a image load task for img.src = img.src per
  // spec.
  //
  // Both cases handle unsetting src in AfterSetAttr
  if (aNameSpaceID == kNameSpaceID_None &&
      aName == nsGkAtoms::src) {

    // This is for dom.disable_image_src_set, which predates "srcset"
    // as an attribute. See Bug 773429
    if (nsContentUtils::IsImageSrcSetDisabled()) {
      return NS_OK;
    }

    if (InResponsiveMode()) {
      if (mResponsiveSelector &&
          mResponsiveSelector->Content() == this) {
        mResponsiveSelector->SetDefaultSource(aValue);
      }
      QueueImageLoadTask(true);
    } else if (aNotify) {
      // 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
      // sync image load from BindToTree. Skip the LoadImage call in that case.

      // Note that this sync behavior is partially removed from the spec, bug 1076583

      // A hack to get animations to reset. See bug 594771.
      mNewRequestsWillNeedAnimationReset = true;

      // Force image loading here, so that we'll try to load the image from
      // network if it's set to be not cacheable...  If we change things so that
      // the state gets in Element's attr-setting happen around this
      // LoadImage call, we could start passing false instead of aNotify
      // here.
      LoadImage(aValue, true, aNotify, eImageLoadType_Normal);

      mNewRequestsWillNeedAnimationReset = false;
    }
  }

  return nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
                                       aNotify);
}
Esempio n. 6
0
void
HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent *aSourceNode,
                                                  bool aNotify)
{
  if (!HTMLPictureElement::IsPictureEnabled()) {
    return;
  }

  MOZ_ASSERT(IsPreviousSibling(aSourceNode, this),
             "Should not be getting notifications for non-previous-siblings");

  // This always triggers the image update steps per the spec, even if
  // we are not switching to/from this source
  QueueImageLoadTask(true);
}
Esempio n. 7
0
void
HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
{
  if (mForm) {
    if (aNullParent || !FindAncestorForm(mForm)) {
      ClearForm(true);
    } else {
      UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
    }
  }

  if (aNullParent &&
      nsINode::GetParentNode()->Tag() == nsGkAtoms::picture &&
      HTMLPictureElement::IsPictureEnabled()) {
    // Being removed from picture re-triggers selection, even if we
    // weren't using a <source> peer
    QueueImageLoadTask();
  }

  nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
  nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
Esempio n. 8
0
void
HTMLImageElement::PictureSourceSrcsetChanged(nsIContent *aSourceNode,
                                             const nsAString& aNewValue,
                                             bool aNotify)
{
  bool isSelf = aSourceNode == this;

  if (!IsSrcsetEnabled() ||
      (!isSelf && !HTMLPictureElement::IsPictureEnabled())) {
    return;
  }

  MOZ_ASSERT(isSelf || IsPreviousSibling(aSourceNode, this),
             "Should not be getting notifications for non-previous-siblings");

  nsIContent *currentSrc =
    mResponsiveSelector ? mResponsiveSelector->Content() : nullptr;

  if (aSourceNode == currentSrc) {
    // We're currently using this node as our responsive selector
    // source.
    mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue);
  }

  if (!mInDocResponsiveContent) {
    nsIDocument* doc = GetOurOwnerDoc();
    if (doc) {
      doc->AddResponsiveContent(this);
      mInDocResponsiveContent = true;
    }
  }

  // This always triggers the image update steps per the spec, even if
  // we are not using this source.
  QueueImageLoadTask(true);
}
Esempio n. 9
0
nsresult
HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                               const nsAttrValue* aValue, bool aNotify)
{
  if (aNameSpaceID == kNameSpaceID_None && mForm &&
      (aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
      aValue && !aValue->IsEmptyString()) {
    // add the image to the hashtable as needed
    MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom,
               "Expected atom value for name/id");
    mForm->AddImageElementToTable(this,
      nsDependentAtomString(aValue->GetAtomValue()));
  }

  // Handle src/srcset/crossorigin updates. 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 image load from BindToTree.

  nsAttrValueOrString attrVal(aValue);

  if (aName == nsGkAtoms::src &&
      aNameSpaceID == kNameSpaceID_None &&
      !aValue) {
    // SetAttr handles setting src since it needs to catch img.src =
    // img.src, so we only need to handle the unset case
    if (InResponsiveMode()) {
      if (mResponsiveSelector &&
          mResponsiveSelector->Content() == this) {
        mResponsiveSelector->SetDefaultSource(NullString());
      }
      QueueImageLoadTask(true);
    } else {
      // Bug 1076583 - We still behave synchronously in the non-responsive case
      CancelImageRequests(aNotify);
    }
  } else if (aName == nsGkAtoms::srcset &&
             aNameSpaceID == kNameSpaceID_None &&
             IsSrcsetEnabled()) {
    PictureSourceSrcsetChanged(this, attrVal.String(), aNotify);
  } else if (aName == nsGkAtoms::sizes &&
             aNameSpaceID == kNameSpaceID_None &&
             HTMLPictureElement::IsPictureEnabled()) {
    PictureSourceSizesChanged(this, attrVal.String(), aNotify);
  } else if (aName == nsGkAtoms::crossorigin &&
             aNameSpaceID == kNameSpaceID_None &&
             aNotify) {
    // Force a new load of the image with the new cross origin policy.
    if (InResponsiveMode()) {
      // per spec, full selection runs when this changes, even though
      // it doesn't directly affect the source selection
      QueueImageLoadTask(true);
    } else {
      // Bug 1076583 - We still use the older synchronous algorithm in
      // non-responsive mode.  Force a new load of the image with the
      // new cross origin policy.
      ForceReload(aNotify);
    }
  }

  return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
                                            aValue, aNotify);
}
Esempio n. 10
0
void
HTMLImageElement::MediaFeatureValuesChanged()
{
  QueueImageLoadTask(false);
}